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

时间:2015-10-13 08:38:56

标签: c# entity-framework linq

下面的代码给了我一个NullReferenceException,堆栈跟踪告诉我问题出在Count方法中,所以我很确定在foo,{{1}或barbaz

我的代码:

null

我想知道处理IQueryable<IGrouping<string, Referral>> queryable= ...; var dict = queryable.ToDictionary(g => g.Key.ToString(), g => g.Count(r => r.foo.bar.baz.dummy == "Success")); 案件的简洁方法是什么。 我了解到在C#6.0中我可以做null,但我正在研究的项目不是C#6.0

4 个答案:

答案 0 :(得分:30)

&lt; 6.0的解决方案是:

.Count(r => r.foo != null && 
            r.foo.bar != null && 
            r.foo.bar.baz != null && 
            r.foo.bar.baz.dummy == "Success")

正好引入了类似于上面的复制结构的空传播算子。

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

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;
}

并按如下方式使用:

g => g.Count(Filter("Success"))

答案 1 :(得分: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);
}

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

return foo
    .With(o => o.bar)
    .With(o => o.baz)
    .Return(o => o.dummy, null);

答案 2 :(得分:2)

问题是ToDictionary方法实际上并没有在查询中完成 - 相反,你得到整个集合,并在应用程序中而不是在数据库服务器上进行聚合。

因此,不要直接使用ToDictionary,而是先使用Select

IQueryable<IGrouping<string, Referral>> queryable= ...;
var dict = queryable.Select(g => new { Key = g.Key.ToString(),
                              Count = g.Count(r => r.foo.bar.baz.dummy == "Success") })
                    .ToDictionary(i => i.Key, i => i.Count);

这将确保聚合在数据库中完成(您不关心那些空值),而不是在C#代码中(您获得NullReferenceException)。

当然,这假设您使用的可查询是一个数据库查询(或者更准确地说,是一个支持聚合的查询,并且具有类似ANSI SQL的NULL语义)。如果你有一个不同的自定义查询,它将无法提供帮助(除非你自己明确地添加那些NULL语义)。

答案 3 :(得分:-1)

// if null, use null 
if(objectvariable == null) 
{
 // throw exception 
}

// if not null
if(objectvariable != null) 
{
 // continue  
}