5

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

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

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

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

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

你调用的对象是空的。

我想念什么?!

4

4 回答 4

6

其中一个可能Thing是。你可以试试这个:subsetnull

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

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

更新:使用 C# 6 中新的空条件运算符(也称为安全导航或“Elvis”运算符),我们可以更简洁地执行相同的操作:

IEnumerable<Thing> subset = things.Where(a => a?.SomeFlag);
于 2013-08-11T19:06:19.950 回答
5

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

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

在第二个片段中,它是对Count()枚举列表的调用,然后才发现其中一个 a是 null in a => a.SomeFlag

于 2013-08-11T19:06:31.090 回答
4

您可以通过一个稍微简化的示例来了解此处实际发生的情况。

Test班级:

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

和 LINQ 查询IEnumerable<Test>

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用check扩展谓词:

IEnumerable<Test> filteredSource = source.Where(x => x != null && x.Value > 10);
于 2013-08-11T19:10:08.417 回答
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,如果.SomeFlagget 访问器具有可能导致 NullReferenceException 的副作用,您仍然可以获得 NullReferenceException。

于 2013-08-11T19:34:04.873 回答