为什么我要在Equals覆盖中执行object.ReferenceEquals(null,this)?

Abe*_*bel 2 .net c# null this referenceequals

请考虑以下我正在审核的代码:

public override bool Equals(object other)
{
    return !object.ReferenceEquals(null, this)
           && (object.ReferenceEquals(this, other)
           || ((other is MyType) && this.InternalEquals((MyType)other)));
}
Run Code Online (Sandbox Code Playgroud)

这段代码的第一行引发了我的好奇心.每当this为null时,该方法应返回false.现在我很确定程序员打算用!object.ReferenceEquals(other, null)快捷方式编写null,但是他坚持认为this可以为null.我坚持认为它不能(除非有人使用直接内存操作).我们应该留下吗?

Jon*_*eet 7

虽然我肯定不会正常检查this为无效,这是可能的,没有任何实际的内存污秽-只是有点反思:

using System;

public class Test
{
    public void CheckThisForNullity()
    {
        Console.WriteLine("Is this null? {0}", this == null);
    }

    static void Main(string[] args)
    {
        var method = typeof(Test).GetMethod("CheckThisForNullity");
        var openDelegate = (Action<Test>) Delegate.CreateDelegate(
               typeof(Action<Test>), method);
        openDelegate(null);
    }
}
Run Code Online (Sandbox Code Playgroud)

或者,生成IL,call而不是callvirt在空目标上调用实例方法.完全合法,不是C#编译器通常会做的事情.

这与终结无关,终结本身就是毛茸茸的,但却以不同的方式.如果CLR可以证明你不会使用实例中的任何字段(我强烈希望包含this引用),那么在实例方法执行时可以运行终结器.

至于提供的代码 - 不,这看起来只是一个错误.我会把它重写为:

public override bool Equals(object other)
{
    return Equals(other as MyType);
}

public bool Equals(MyType other)
{
    if (ReferenceEquals(other, null))
    {
        return false;
    }
    // Now perform the equality check
}
Run Code Online (Sandbox Code Playgroud)

...假设这MyType是一个类,而不是结构.请注意我如何使用具有正确参数类型的另一个公共方法 - 我将同时实现IEquatable<MyType>.