对象引用未设置为实例,但不为null

本文关键字:null 实例 设置 对象引用 | 更新日期: 2023-09-27 18:27:25

我的流程中出现了一些意外行为。我正在做以下事情。

IEnumerable<Thing> things = ...;
IEnumerable<Thing> subset = things.Where(a => a.SomeFlag);
String info = "null: " + (subset == null);

上面的工作和信息告诉我对象不是。所以我想通过这个来检查子集中元素的数量。

IEnumerable<Thing> things = ...;
IEnumerable<Thing> subset = things.Where(a => a.SomeFlag);
String info = "null: " + (subset == null);
String count = subset.Count();

现在我得到一个异常,给我错误消息:

对象引用未设置为对象的实例。

我想念什么?!

对象引用未设置为实例,但不为null

subset中的一个Thing可能是null。你可以试试这个:

IEnumerable<Thing> subset = things.Where(a => a != null && a.SomeFlag);

请注意,由于Linq的惰性求值方式,您不会得到任何称为.Where的异常,因为它在这一点上所做的只是设置一个过滤things元素的条件。只有当您稍后调用.Count时,它才真正评估结果。

更新:使用C#中新的null条件运算符(也称为安全导航或"Elvis"运算符),我们可以更简洁地做同样的事情:

IEnumerable<Thing> subset = things.Where(a => a?.SomeFlag);

IEnumerable<Thing>表示延迟执行。

在您的第一个片段中,subsetthings从未被枚举。

在第二个片段中,是对Count()的调用枚举了这些列表,直到这时才发现其中一个aa => a.SomeFlag中为空。

您可以通过一个稍微简化的示例看到这里真正发生了什么。

Test类:

public class Test
{
    public int Value { get; set; }
}

以及对IEnumerable<Test>:的LINQ查询

IEnumerable<Test> source = new List<Test>() {
    new Test { Value = 10 },
    null,
    new Test { Value = 20 }
};
IEnumerable<Test> filteredSource = source.Where(x => x.Value > 10);
// return false
Console.WriteLine(filteredSource == null);
// throws NullReferenceException
Console.WriteLine(filteredSource.Count());

为什么会发生这种情况?因为filteredSource == null不会导致集合枚举,所以不会在任何source集合元素上激发Where谓词。

但是,当您在filteredSource上调用Count()时,谓词将在source集合中的每个项上调用,当涉及到null的项时:null.Value > 10将抛出异常。

如何使其发挥作用?用x != null检查扩展谓词:

IEnumerable<Test> filteredSource = source.Where(x => x != null && x.Value > 10);

好的,假设您在things中有以下项目:

Thing A  SomeFlag = true
Thing B  SomeFlag = false
null
Thing C  SomeFlag = true

首先计算things中的所有项目。因此,您对4个对象进行迭代,找到4个对象,结果为4。容易的

现在您要计算subset中的所有项目,这意味着您首先需要计算出subset中的哪些项目。所以你开始计算它们:

Thing A .... A.SomeFlag is true, so count it
Thing B .... B.SomeFlag is not true, so don't count it
null    .... null.SomeFlag  NULLREFERENCEEXCEPTION

这就是你的错误来源。

请注意,即使事物中的所有元素都不为null,如果.SomeFlag get访问器具有可能导致NullReferenceException的副作用,则仍然可以获得NullReferencesException。