【问题标题】:Why does String.Equals(Object obj) check to see if this == null? [duplicate]为什么 String.Equals(Object obj) 检查 this == null? [复制]
【发布时间】:2012-04-27 11:34:46
【问题描述】:

可能重复:
Why check this != 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 是否为空。评论有点混乱,所以我想知道该评论的真正含义是什么?

谁能举例说明如果不存在该检查会如何中断,这是否意味着我也应该将该检查放入我的课程中?

【问题讨论】:

  • @FlorianGreinacher:不可能重复,但几乎完全一样,哈哈。我想知道为什么在我写问题时它没有出现在“相关”中?

标签: c# .net string pinvoke null-check


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:
    • C# 和 VB.NET 等语言使用 callvirt 在输入实例方法之前抛出 NullReference(this == null)检查是不必要的。
    • F# 和托管 C++ 等语言(大多数情况下)使用 call 指令,您可以在其中使用空 this 指针进入实例方法。 (this == null) 确实有效果。

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

    如果您查看 .NET 类中的检查,很明显,只有在一些突出的类(如字符串)中才包含此类保护。其他方法,如 IndexOf 并不能防止这种情况。这是不一致的,但我确实认为这种双重空值检查的性能损失不值得付出努力,因为 BCL 的大多数用户都是使用 callvirt 指令的语言,而第二次空值检查没有帮助。

    【讨论】:

    • 在 F# 中,let x = "a".Equals("b") 仍然编译为 callvirt
    猜你喜欢
    • 2016-09-15
    • 2011-01-21
    • 1970-01-01
    • 2020-04-07
    • 2015-12-07
    • 2016-06-16
    • 1970-01-01
    • 2020-11-07
    相关资源
    最近更新 更多