不,这是一个空引用异常,就像访问var x = u.Address.Country.Code; 将是一个NullReferenceException。
您必须始终确保您在 LINQ to 对象中取消引用的不是 null,就像您在任何其他代码语句中所做的那样。
您可以使用您拥有的&& 逻辑来执行此操作,也可以链接Where 子句(尽管这将包含更多迭代器并且可能执行得更慢):
var result = Users.Where(u => u.Address != null)
.Where(u.Address.Country != null)
.Where(u.Address.Country.Code == 12);
注意:下面的Maybe() 方法只是作为“你也可以”的方法提供,我并不是说它的好坏,只是展示了一些人的做法。如果您不喜欢Maybe(),请不要投反对票,我只是在重复我见过的各种解决方案...
我见过一些Maybe() 扩展方法,它们可以让你做你想做的事情。有些人喜欢/不喜欢这些,因为它们是在 null 引用上运行的扩展方法。我并不是说那是好是坏,只是有些人认为这违反了良好的类似 OO 的行为。
例如,您可以创建如下扩展方法:
public static class ObjectExtensions
{
// returns default if LHS is null
public static TResult Maybe<TInput, TResult>(this TInput value, Func<TInput, TResult> evaluator)
where TInput : class
{
return (value != null) ? evaluator(value) : default(TResult);
}
// returns specified value if LHS is null
public static TResult Maybe<TInput, TResult>(this TInput value, Func<TInput, TResult> evaluator, TResult failureValue)
where TInput : class
{
return (value != null) ? evaluator(value) : failureValue;
}
}
然后做:
var result = Users.Where(u => u.Maybe(x => x.Address)
.Maybe(x => x.Country)
.Maybe(x => x.Code) == 12);
本质上,这只是将null 向下级联(或在非引用类型的情况下为默认值)。
更新:
如果你想提供一个非默认的失败值(假设代码为 -1,如果任何部分为空),你只需将新的失败值传递给 Maybe():
// if you wanted to compare to zero, for example, but didn't want null
// to translate to zero, change the default in the final maybe to -1
var result = Users.Where(u => u.Maybe(x => x.Address)
.Maybe(x => x.Country)
.Maybe(x => x.Code, -1) == 0);
就像我说的,这只是众多解决方案之一。有些人不喜欢能够从 null 引用类型调用扩展方法,但有些人倾向于使用它来解决这些 null 级联问题。
然而,目前 C# 中没有内置的空安全取消引用运算符,因此您要么像以前那样使用条件空检查,链接您的 Where() 语句,以便它们将过滤掉 @ 987654338@,或者构建一些东西让你级联null,就像上面的Maybe()方法一样。