对象引用未设置为实例而不为空

时间:2013-08-11 19:04:26

标签: c#

我的过程中出现了一些意想不到的行为。我正在做以下事情。

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

上述作品和 info 告诉我该对象不是 null 。所以我希望通过这个来检查子集中的元素数量。

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

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

  

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

我想念什么?!

4 个答案:

答案 0 :(得分:5)

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

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

请注意,由于Linq的懒惰评估方式,您无法获得拨打.Where的任何异常,因为此时所做的一切都是为此设置条件过滤things的元素。只有在您致电.Count之后才会实际评估结果。

更新:使用C#6中的新null-condition operator(也称为安全导航或&#39; Elvis&#39;运营商),我们可以做同样的事情简洁地:

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

答案 1 :(得分:5)

IEnumerable<Thing>意味着延迟执行。

在您的第一个片段中,subsetthings永远不会被枚举。

在第二个片段中,对Count()的调用枚举了列表,然后才发现a中的a => a.SomeFlag之一为空。

答案 2 :(得分:3)

你可以通过一些简化的例子看到这里真正发生的事情。

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不会导致集合枚举,因此不会在任何Where集合元素上触发source谓词。

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

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

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

答案 3 :(得分:2)

好的,假设您在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的副作用,您仍然可以获得NullReferenceException。