Null在调用链中合并

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

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

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

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

你正在寻找.? C#中不存在运算符(或者它是?. – 其中之一) – 尽管它是一种经常被请求的function,根据Eric Lippert的说法。

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

 T TryOrDefault(Expression> 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 func = expression.Compile(); return func(); } 

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

 public static U AndAnd(this T obj, Func 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)返回的default(U)

为它创建一个单独的函数

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

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

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