空调在调用链中合并

时间:2011-02-10 14:12:28

标签: c# linq nullreferenceexception null-coalescing-operator

如果我有一长串对象,每个对象都有可能在“Linq where”子句中返回null,例如

 SomeSource.Where(srcItem=>(srcItem.DataMembers["SomeText"].Connection.ConnectedTo as Type1).Handler.ForceInvocation == true));

索引器可以返回null,“as”运算符可以返回null。对象可能没有连接(即属性为null)。 如果在任何地方遇到null,我希望where子句为被评估的项返回“false”。相反,它以空引用异常中止。

在我看来,这将被设计为在单个C#表达式中表达。我不喜欢创建一个多行语句或为它创建一个单独的函数。 我是否缺少使用空合并运算符?

4 个答案:

答案 0 :(得分:2)

你正在寻找.?运营商(或者它是?. - 其中一个,无论如何),这在C#中是不存在的(尽管它是一个经常被要求的功能,根据Eric Lippert)。

我唯一的可能的建议是编写一个方法,该方法采用表达式并使用 it 来检查任何空值。但这将带来性能成本。无论如何,它可能看起来像:

T TryOrDefault<T>(Expression<Func<T>> expression)
{
    // Check every MemberExpression within expression one by one,
    // looking for any nulls along the way.

    // If a null is found, return default(T) or some default value.

    // Otherwise...
    Func<T> func = expression.Compile();
    return func();
}

答案 1 :(得分:2)

使用Ruby的andand运算符作为灵感,您可以创建一个充当空值保护的扩展方法。

public static U AndAnd<T, U>(this T obj, Func<T, U> func)
{
    return obj == null ? default(U) : func(obj);
}

然后可以按如下方式重写原始代码:

SomeSource.Where(srcItem => (srcItem.AndAnd(val => val.DataMembers["SomeText"]).AndAnd(val => val.Connection).AndAnd(val => val.ConnectedTo) as Type1).AndAnd(val => val.Handler).AndAnd(val => val.ForceInvocation));

使用此方法返回非布尔值类型时要小心 - 确保default(U)返回familiar with the values

答案 2 :(得分:0)

  

为它创建一个单独的函数

这是要走的路。不要对适当的技术过敏。您创建的方法(在运行时和概念上)并不比匿名方法更昂贵。

答案 3 :(得分:0)

前段时间我写了一个模仿AndAnd的项目依赖于DynamicProxy。它工作正常,虽然我没有在产品中使用它。唯一的缺点是它需要所有成员都是虚拟的或返回的类型是一个接口,所以DynamicProxy可以发挥它的魔力。

在这里查看 https://bitbucket.org/mamadero/andand/overview