LINQ:当对象可能为空时选择属性的更好方法?

Vok*_*Vok 2 c# linq

var result = foo.FirstOrDefault(f => f.bar == barVal).someProperty
Run Code Online (Sandbox Code Playgroud)

如果没有匹配项(默认为 null),这将不起作用 - 尝试访问 null 对象上的属性。我们可以重写如下:

var result = foo.Where(f => f.bar == barVal)
                .Select(f => f.someProperty).DefaultIfEmpty(0).First()
Run Code Online (Sandbox Code Playgroud)

虽然它有效,但这似乎不是最优雅的方法......有更好的方法吗?


当然,人们可以做一些事情,例如:

var result = 0;
var tmp = foo.FirstOrDefault(f => f.bar == barVal);
if(tmp != null) result = tmp.someProperty
Run Code Online (Sandbox Code Playgroud)

但在更复杂的查询中,这种方法看起来比 DefaultIfEmpty 方法更“混乱”

var tmpSet = dataSet.GroupBy(f => f.ID);
var newSet = tmp.Select(f => new { 
               ID = f.ID,
               SomeProperty = f.Where(g => g.bar == barVal)
                               .Select(f => f.SomeProperty)
                               .DefaultIfEmpty(0).First()
               });
Run Code Online (Sandbox Code Playgroud)

Tho*_*que 5

你可以这样做:

var result = foo.Where(f => f.bar == barVal)
                .Select(f => f.someProperty)
                .FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)

或者您可以编写自定义扩展方法:

public static TResult IfNotNull<TSource, TResult>(this TSource instance, Func<TSource, TResult> getter, TResult defaultValue = default(TResult))
    where TSource : class
{
     if (instance != null)
          return getter(instance);
     return defaultValue;
}

...

var result = foo.FirstOrDefault(f => f.bar == barVal)
                .IfNotNull(f => f.someProperty);
Run Code Online (Sandbox Code Playgroud)

编辑:使用 C# 6,您将能够编写以下内容:

var result = foo.FirstOrDefault(f => f.bar == barVal)?.someProperty ?? 0;
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅Roslyn Codeplex 网站上的讨论。