C#Ordered enumerable - 对象引用未设置为对象的实例

时间:2016-06-02 14:57:01

标签: c# linq nullreferenceexception enumerable

我有以下代码:

// OnlineAccountCategory is a class
var itemsByCategory = Items.GroupBy(x => x.OnlineAccountCategory); 
foreach (var items in itemsByCategory)
...

项目是包含1个项目的列表。商品的OnlineAccountCategory不是null。但是,当我尝试通过itemsByCategory时,我会收到NullReferenceException。在调试模式中,我可以看到itemsByCategoryGroupedEnumerable,但如果我展开结果视图,它将告诉它'对象引用未设置为对象的实例& #39;

我不太明白这段代码的问题是什么,因为GroupBy()没有任何异常,但是在foreach循环中中断了。

2 个答案:

答案 0 :(得分:2)

这里的问题是OnlineAccountCategory是引用类型属性(而不是字符串或类似的东西)。按引用类型分组使用发生分组的类的方法GetHashCode()

关键是如果GetHashCode()方法抛出异常(例如,如果它依赖于使用我们的对象的属性null),GroupBy()方法赢了& #39; t失败。由于某种原因,它只会返回一个包含异常的GroupedEnumerable

// Trying to add this to watch:     
Items.First().OnlineAccountCategory.GetHashCode()   
// Receiving: 
'Items.First().OnlineAccountCategory.GetHashCode()' threw an exception of type 
'System.NullReferenceException' int {System.NullReferenceException}

因此,当我们尝试访问集合的元素时,它会落在NullReferenceException

要解决这个问题,我们有两种方法:

  1. 覆盖我们GetHashCode的{​​{1}}方法 所以它不会在错误的值上失败,而不是抛出一个 异常将返回类似0的内容。

  2. 按一些值类型分组(例如,     OnlineAccountCategory)。它将由它组合,因此赢了     失败。

  3. <强>更新OnlineAccountCategory.Id方法已经错误地实现(在我的情况下在基类中实现)时,问题将出现。默认参考比较器将按预期使用。

    我的GetHashCode()方法如下所示:

    GetHashCode()

    所以我真的不明白为什么它会在这里打破NullReferenceException。

答案 1 :(得分:1)

我很高兴您解决了问题但我不认为您完全理解错误的原因。

  

我不太明白这段代码的问题是什么,因为GroupBy()没有任何异常,但在foreach循环中中断了。

在执行foreach之前您没有看到错误的原因是延迟执行。在您尝试枚举集合之前,GetHashCode不会被称为。如果GetHashCode正在抛出NullReferenceException,那么在您使用foreach执行查询之前,您将不会知道这一点,这是实际创建组的时间。

当然, root 原因是您的错误GetHashCode方法,可以在单元测试中轻松检测到。

请注意,在不覆盖GetHashCode的情况下按引用类型进行分组是完全可以的,因为任何空值都只会放入一个带有null键的组中(Linq不会尝试调用{{1}在null引用上)。如果要根据实例的值定义不同实例的相等性,而不是默认使用引用相等性,则只需需要覆盖GetHashCode