【问题标题】:More graceful solution to nested Linq queries?嵌套 Linq 查询的更优雅的解决方案?
【发布时间】:2016-01-07 22:23:24
【问题描述】:

我有一组嵌套的 linq 查询,用于从属性列表中获取属性。它按原样工作得很好,但有一个警告。我必须进行错误处理,以防万一没有合适的匹配。是否有类似的方法可以在不使用 try-catch 块的情况下完成以下代码的工作?

try
{
    organization =
    _orgs.FirstOrDefault(n => 
        n.OrganizationFields.FirstOrDefault(nn => 
            nn.Key == "customer_id").Value.ToString() == id);
}
catch (InvalidOperationException)
{
    return null;
}
catch (NullReferenceException)
{
    return null;
}

【问题讨论】:

  • 组织与组织字段是一对多的吗?如果是这种情况,那么您可以使用 _orgs.OrganizationFields(where id 上的子句).Select(n => n._org).FirstOrDefault(); 开始查询如果没有匹配项应该返回 null 而不会导致异常
  • firstordefault 本身不会抛出 InvalidOperationException。在您的代码中似乎永远不会发生异常(如果您不将其抛出到属性的获取器中)。所以捕获是无用的。
  • @M.kazemAkhgary _orgs or OrganizationFields or .ToString() 都可能抛出空引用异常:)

标签: c# linq refactoring


【解决方案1】:

如果您使用的是 C# 6,则可以使用 Null Conditional Operator

organization =
_orgs?.FirstOrDefault(n => 
    n.OrganizationFields?.FirstOrDefault(nn => 
        nn.Key == "customer_id")?.Value.ToString() == id);

这是一个完整的程序,展示了它的实际效果

class Bar
{
    public string Text { get; set; }
}

class Foo
{
    public List<Bar> Bars { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        Foo foo = new Foo(); // Note that foo.Bars is still null

        string text = foo.Bars?.FirstOrDefault()?.Text;

        Console.WriteLine(text);
    }
}

【讨论】:

  • 不幸的是,在.Value 之前,我在? 上收到一个错误,说...Can't apply operand to type... KeyValuePair
  • @Jdsfighter 你在用 C#6 吗?
  • 是的,我是。所有其他 ? 操作员都工作了。只是不是Value之前的那个@
  • @Jdsfighter 哦,是的,KeyValuePair&lt;TKey,TValue&gt; 是一个不可为空的结构。在这种情况下,您可以删除 ?,因为它保证不会为空。
  • 原来是Value 部分实际上是空的。通过在ValueToString 之间移动? 操作数,错误已得到修复。
【解决方案2】:

我不知道你为什么需要捕捉InvalidOperationException,所以我会忽略它。 NullReferenceException 怎么样,我假设它只能由 FirstOrDefault(...).Value 调用生成(如果您遵循最佳实践,_orgsn.OrganizationFieldsValue 都不应该是 null)。

如果上述假设是正确的,那么下面的代码应该相当于不需要异常处理程序的示例代码

organization = _orgs.FirstOrDefault(n => n.OrganizationFields
    .Any(nn => nn.Key == "customer_id" && nn.Value.ToString() == id));

根据您的评论,如果 Value 可以是 null,则在 C#6 中使用 nn.Value?.ToString() == ...,或者在 C#6 之前使用 nn.Value != null &amp;&amp; nn.Value.ToString() == ...

【讨论】:

  • InvalidOperationException 是我使用 First 而不是 FirstOrDefault 时的保留。
  • 当我将 nn.Value.ToString() 更改为 nn.Value?.ToString() 时,您的解决方案有效。看起来是 Value 属性为空。
  • 嗯,这是我提到的假设,因为您没有提供足够的信息。无论如何。
猜你喜欢
  • 2018-04-28
  • 1970-01-01
  • 2015-07-03
  • 1970-01-01
  • 1970-01-01
  • 2011-04-18
  • 1970-01-01
  • 1970-01-01
  • 2011-03-31
相关资源
最近更新 更多