下面的代码给了我一个NullReferenceException
,堆栈跟踪告诉我问题出在Count
方法中,所以我很确定在foo
,{{1}或bar
是baz
。
我的代码:
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
答案 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
}