为什么String.Equals(Object obj)检查这是否== null?

可能重复:
为什么检查这个!= 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); } 

我不理解的部分是它正在检查当前实例,而不是null。 评论有点令人困惑,所以我想知道这个评论究竟意味着什么?

任何人都可以给出一个例子,说明如果那个检查不存在,这可能会破坏,这是否意味着我还应该将检查放在我的课程中?

该检查用于防止本机代码,可以使用null this指针调用该函数。 这在C#中不可能发生,因此您不必在代码中添加类似的警卫。 很可能String类是在C#最终确定之前编写的,并且作者可能认为防止空值很重要,或者通常从本机代码和其他地方调用String方法可以很容易地调用null上的方法。

请注意,即使您确实设法使用null进行调用,并且您没有防护,所有会发生的情况是exception会略有不同。 它可能是一个不同的例外,它可能会被另一个成员抛出,但否则它不太可能产生影响。

换句话说,如果没有null检查,则EqualsHelper (或其中一个被EqualsHelper )将抛出exception而不是Equals 。 由于需要隐藏用户可见function的内部结构,因此将检查放在开头是有意义的。

  • 像C#和VB.NET这样的语言在输入实例方法(此== null)检查之前使用callvirt来抛出NullReference。
  • 像F#和Managed C ++这样的语言(大多数时候)使用call指令,你可以使用null指针进入实例方法。 (这= = null)确实有效果。

添加的空值检查不仅适用于后面的语言,还有助于调试可以在错误(调用空对象的实例方法)确实发生的位置抛出。 如果它不在那里你可以调用类中的任何方法而没有任何错误,只要这永远不会解除引用(访问成员变量)。 这可以到目前为止,在您的null对象上,几个方法调用确实起作用,然后突然得到一个空引用exception(实例数据被访问的方法)。

如果你查看.NET类中的检查,很明显只有像字符串这样的一些突出的类包含这样的警卫。 像IndexOf这样的其他方法并不能防范这种情况。 这是不一致的,但我认为这种双重空检查的性能损失并不值得,因为BCL的大多数用户都是使用callvirt指令的语言,其中第二次空检查没有帮助。