在C#6.0之前处理NullReferenceException的好方法

Arc*_*ect 18 c# linq entity-framework

我下面的代码给了我一个NullReferenceException和堆栈跟踪告诉我问题在于Count方法,所以我很确定在某个时候foo,bar或者baznull.

我的代码:

IQueryable<IGrouping<string, Referral>> queryable= ...;
var dict = queryable.ToDictionary(g => g.Key.ToString(),
                                  g => g.Count(r => r.foo.bar.baz.dummy == "Success"));
Run Code Online (Sandbox Code Playgroud)

我想知道处理null案件的简洁方法是什么.我知道在C#6.0中我可以做到foo?.bar?.baz?.dummy,但我正在研究的项目不是C#6.0

Mic*_*ger 30

<6.0的解决方案是:

.Count(r => r.foo != null && 
            r.foo.bar != null && 
            r.foo.bar.baz != null && 
            r.foo.bar.baz.dummy == "Success")
Run Code Online (Sandbox Code Playgroud)

正好适用于复杂的构造,如上面的空传播算子.

此外,您还可以将表达式重构为私有方法:

private Expression<Func<Referral, bool>> Filter(string value)
{
    return r => r.foo != null && 
                r.foo.bar != null && 
                r.foo.bar.baz != null && 
                r.foo.bar.baz.dummy == value;
}
Run Code Online (Sandbox Code Playgroud)

并按如下方式使用:

g => g.Count(Filter("Success"))
Run Code Online (Sandbox Code Playgroud)


Ser*_*diy 9

您可以使用以下扩展方法.

public static TResult With<TInput, TResult>(this TInput o, Func<TInput, TResult> evaluator)
    where TResult : class
    where TInput : class
{
    return o == null ? null : evaluator(o);
}

public static TResult Return<TInput, TResult>(this TInput o, Func<TInput, TResult> evaluator, TResult failureValue)
    where TInput : class
{
    return o == null ? failureValue : evaluator(o);
}
Run Code Online (Sandbox Code Playgroud)

它们的组合为您提供了一个漂亮,可读的API来处理nulls:

return foo
    .With(o => o.bar)
    .With(o => o.baz)
    .Return(o => o.dummy, null);
Run Code Online (Sandbox Code Playgroud)

  • 虽然这是一个好主意,但它与`IQueryable`并不顺利.LINQ不会理解这一点,并且thuis在客户端而不是在数据库上执行查询. (4认同)