如果null.Equals(null),为什么会出现NullReferenceException异常?

19

我有以下代码行:

var selectedDomainID = lkuDomainType.EditValue.Equals(null) 
    ? string.Empty 
    : lkuDomainType.EditValue;
有时会出现NullReferenceException的情况,我不明白的是为什么。我的代码的整个意图不就是检查是否为null,如果是则分配string.empty吗?在调试中检查时,它表示EditValue == null ,那我错过了什么吗?

2
lkuDomainType本身不能为null吗?当您调用lkuDomainType.EditValue时,它会抛出NullReferenceException异常。 - Saher Ahwal
2
因为你的标题:“a == b”不等同于“a.Equals(b)”。 - Stefan Steinegger
@Stefan:非常好的观点!已更正以便于未来的搜索者...谢谢 - Refracted Paladin
可能是什么是NullReferenceException,我该如何修复它?的重复问题。 - user247702
10个回答

32

使用 lkuDomainType.EditValue == null,否则您将尝试在空对象上调用一个实例方法。但更好的选择可能是 lkuDomainType.EditValue ?? String.Empty。此外,请注意 lkuDomainType 是否为 null,除非它是一个类而不是一个对象。


1
谢谢,事后看来很明显,绝对是一个“傻瓜”时刻。谢谢。 - Refracted Paladin
5
+2(不幸的是不可能)对于正确答案和建议使用“??”。 - Stefan Steinegger
+1:空合并运算符(或者 ??)是 .NET 的一个很好的补充,每当我使用 Java 时都非常想念它。 - Powerlord

16

当你使用 Object.Property 并且 Object 未定义时,你正在取消引用一个空指针,这就是为什么会出现异常的原因。相反,应该使用:

var selectedDomainID = lkuDomainType.EditValue == null ? string.Empty : lkuDomainType.EditValue;

5
我必须点赞这个答案,一是因为它回答正确,二是因为在句子中使用了“dereference”,三是因为用户名几乎适合。 - Giuseppe Accaputo
很好的回答,+1,但是SO说@Yuriy的回答更早。不过还是谢谢。 - Refracted Paladin
2
@Refracted 是的,比4秒慢 :) 我喜欢他/她使用 ?? 的建议。 - NullUserException
@Refracted 是的,你说得对。我忘了提到我也为Yuriy的答案点了赞,因为他使用了??运算符。 - Giuseppe Accaputo
在这种情况下,它是 Object.Property.Method,如果 ObjectProperty 未定义,则会取消引用空指针。 - Powerlord

5
如果 EditValue 为空,则无法调用 Equals。在这种情况下,您需要执行以下操作:
var selectedDomainID = lkuDomainType.EditValue == null ? string.Empty : lkuDomainType.EditValue;

或者您可以简化它,只需执行以下操作:

var selectedDomainID = lkuDomainType.EditValue ?? string.Empty;

3
您正在尝试在一个空对象上调用Equals方法 - 请按照以下方式进行操作:
lkuDomainType.EditValue == null

3
问题在于您在检查对象是否为null之前就使用了它。您调用了对象的Equals方法,如果引用为null,则会失败。
您需要将您的“lkuDomainType.EditValue.Equals(null)”更换为“lkuDomainType.EditValue == null”。

2

在这里应该使用String.IsNullOrEmpty。像这样:

var selectedDomainID = String.IsNullOrEmpty(lkuDomainType.EditValue) ? string.Empty : lkuDomainType.EditValue;

Equals是一个方法,你正在尝试调用一个空对象上的方法,这会引发异常。


我不明白,String.IsNullOrEmpty 不也是一个 方法 吗? - Refracted Paladin
这是一个静态方法,不是lkuDomainType.EditValue对象的方法。 - brendan

2
当 EditValue 为空时,您无法调用 Equals 方法,因此最好的检查方法是使用:
lkuDomainType.EditValue == null ? string.Empty : lkuDomainType.EditValue;

2

EditValue == null。这意味着那里没有对象。即使函数是.Equals(),也无法在空对象上调用函数。

在这种情况下,最好只说“(lkuDomainType.EditValue == null)”。


1

所有当前的答案都没有解决一个关键点:在调用Nullable类型(它是一个struct)和class类型上的Equals之间的区别。

对于值为null的Nullable类型对象调用Equals不会引发异常,而对于class类型对象则会。

考虑以下代码:

int? num = null; // int? is Nullable<int>
String s = null; // String is a class

var equalsNullable = num.Equals(null); // works
var equalsClass = s.Equals(null);      // throws

原因是在这种情况下调用了NullableHasValue方法,请参见Jon Skeet's answer以获取更多信息。

正如其他人所说,OP的情况下应该使用==??


0
如果lkuDomainType.EditValue为null,则“lkuDomainType.EditValue.Equals(someObject)”与编写“null.Equals(someObject)”相同。显然,“null”没有任何成员或方法(如果有,它就不会是null)。这就是为什么会出现NullReferenceException的原因。
其他帖子中的大多数示例都可以正常工作,包括String.IsNullOrEmpty,它是一个返回布尔值的方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接