6

可能重复:
为什么要检查这个!= null?

// Determines whether two strings match. 
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] 
public override bool Equals(Object obj)
{
    //this is necessary to guard against reverse-pinvokes and
    //other callers who do not use the callvirt instruction
    if (this == null)
        throw new NullReferenceException();

    String str = obj as String;
    if (str == null) 
        return false;

    if (Object.ReferenceEquals(this, obj)) 
        return true;

    return EqualsHelper(this, str);
}

我不明白的部分是它正在检查当前实例,this,反对空值。该评论有点令人困惑,所以我想知道该评论实际上是什么意思?

任何人都可以举一个例子来说明如果该检查不存在,这将如何中断,这是否意味着我也应该将该检查放在我的课程中?

4

2 回答 2

6

该检查是为了防止本机代码使用空this指针调用函数。这在 C# 中不会发生,因此您不必在代码中放置类似的保护措施。很有可能这个String类是在 C# 完成之前编写的,作者可能认为防止空值很重要,或者String从本机代码和其他地方调用方法很常见,这样可以很容易地在空值上调用方法。

请注意,即使您确实设法用 null 调用this并且您没有警卫,所发生的只是异常会略有不同。它可能是一个不同的异常,它可能会被不同的成员抛出,但否则它不太可能产生影响。

换句话说,如果不存在 null 检查,则EqualsHelper(或其被调用者之一) 将抛出异常而不是Equals. 由于希望隐藏用户可见函数的内部结构,因此将检查放在开头是有意义的。

于 2012-04-16T05:33:26.853 回答
2
  • C# 和 VB.NET 等语言使用 callvirt 在输入实例方法之前抛出 NullReference(this == null)检查是不必要的。
  • 像 F# 和托管 C++(大部分时间)这样的语言使用 call 指令,您可以在其中使用 null this 指针进入实例方法。(this == null) 确实有效果。

添加的空检查不仅适用于后一种语言,而且还有助于在发生错误的位置(调用空对象的实例方法)进行调试。如果它不存在,您可以调用类中的任何方法而不会出现任何错误,只要它永远不会取消引用(访问成员变量)。这可能会导致在您的空对象上,几个方法调用确实有效,然后您突然得到一个空引用异常(访问实例数据的方法)。

If you look at the checks inside the .NET classes it is clear that only on some prominent classes like string do contain such guards. Other methods like IndexOf do not guard against this. This is inconsistent but I do think the performance penalty for such double null checks were not worth the effort because most users of the BCL are languages which uses the callvirt instruction where a second null check does not help.

于 2012-04-16T06:33:40.937 回答