[英]Object reference not set to an instance while not being null
I'm getting some unexpected behavior in my process. 我在我的过程中遇到了一些意想不到的行为。 I'm doing the following. 我正在做以下事情。
IEnumerable<Thing> things = ...;
IEnumerable<Thing> subset = things.Where(a => a.SomeFlag);
String info = "null: " + (subset == null);
The above works and info tells me that the object isn't null . 上面的工作和信息告诉我该对象不为null 。 So I wish to check the number of the elements in subset by this. 所以我希望通过这个来检查子集中元素的数量。
IEnumerable<Thing> things = ...;
IEnumerable<Thing> subset = things.Where(a => a.SomeFlag);
String info = "null: " + (subset == null);
String count = subset.Count();
Now I get an exception giving me the error message: 现在我得到一个例外,给我错误信息:
Object reference not set to an instance of an object. 你调用的对象是空的。
What do I miss?! 我错过了什么?!
It's possible that one of the Thing
's in subset
is null
. 有可能其中一个Thing
的subset
为null
。 You can try this: 你可以试试这个:
IEnumerable<Thing> subset = things.Where(a => a != null && a.SomeFlag);
Note that due to the way Linq's lazy evaluation, you won't get any exception you call .Where
because all it's doing at that point is setting up a condition for filtering the elements of things
. 请注意,由于Linq的懒惰评估方式,你不会得到你调用的任何异常.Where
因为它在那时所做的只是设置过滤things
元素的条件。 Only later when you call .Count
is it actually evaluating the results. 只有在你调用.Count
才会实际评估结果。
Update: With the new null-condition operator in C# 6 (also called the safe navigation or 'Elvis' operator), we can do the same thing a bit more succinctly: 更新:使用C#6中的新的null条件运算符 (也称为安全导航或'Elvis'运算符),我们可以更简洁地执行相同的操作:
IEnumerable<Thing> subset = things.Where(a => a?.SomeFlag);
An IEnumerable<Thing>
implies deferred execution. IEnumerable<Thing>
意味着延迟执行。
In your first fragment subset
and things
are never enumerated. 在您的第一个片段subset
, things
永远不会被枚举。
In the second fragment, it is the call to Count()
that enumerates the lists and only then it comes to light that one of the a
is null in a => a.SomeFlag
. 在第二个片段中,对Count()
的调用枚举了列表,然后才发现a => a.SomeFlag
中a => a.SomeFlag
中的a
为null。
You can see what really happens here with a bit simplified example. 你可以通过一些简化的例子看到这里真正发生的事情。
Test
class: Test
类:
public class Test
{
public int Value { get; set; }
}
And LINQ query on IEnumerable<Test>
: 和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());
Why does it happens? 为什么会这样? Because filteredSource == null
does not cause collection enumeration , so Where
predicate is not being fired on any source
collection element. 由于filteredSource == null
不会导致集合枚举 ,所以Where
谓语不被任何上触发source
集合元素。
However, when you call Count()
on filteredSource
the predicate is being called on every item from source
collection, and when it comes to an item which is null
: null.Value > 10
throws the exception. 但是,当您在filteredSource
上调用Count()
,将对source
集合中的每个项调用谓词,并且当涉及到null
的项时: null.Value > 10
将抛出异常。
How to make it work? 如何使它工作? Extend the predicate with x != null
check: 使用x != null
检查扩展谓词:
IEnumerable<Test> filteredSource = source.Where(x => x != null && x.Value > 10);
Ok, so suppose you had the following items in things
: 好了,假设你有以下项目things
:
Thing A SomeFlag = true
Thing B SomeFlag = false
null
Thing C SomeFlag = true
First you count all the items in things
. 首先,你指望在所有项目things
。 So you iterate over 4 objects, find 4 objects, and know that the result is 4. Easy. 所以你迭代4个对象,找到4个对象,并且知道结果是4.简单。
Now you want to count all of the items in subset
which means you need to figure out which items are in subset
in the first place. 现在,您想要计算subset
所有项目,这意味着您需要首先确定哪些项目属于subset
。 So you go about counting them: 所以你要计算它们:
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
And that's where your error comes from. 这就是你的错误来自哪里。
Note that even if all of the elements in things are not null, you can still get a NullReferenceException if the .SomeFlag
get accessor has a side effect that could cause a NullReferenceException. 请注意,即使事物中的所有元素都不为null,如果.SomeFlag
get访问器具有可能导致NullReferenceException的副作用,您仍然可以获得NullReferenceException。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.