如果我有一长串对象,每个对象都有可能在“Linq where”子句中返回null,例如
SomeSource.Where(srcItem=>(srcItem.DataMembers["SomeText"].Connection.ConnectedTo as Type1).Handler.ForceInvocation == true));
索引器可以返回null,“as”运算符可以返回null。对象可能没有连接(即属性为null)。 如果在任何地方遇到null,我希望where子句为被评估的项返回“false”。相反,它以空引用异常中止。
在我看来,这将被设计为在单个C#表达式中表达。我不喜欢创建一个多行语句或为它创建一个单独的函数。 我是否缺少使用空合并运算符?
答案 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可以发挥它的魔力。