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

时间:2013-01-30 21:02:55

标签: c# .net 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)));
}

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

2 个答案:

答案 0 :(得分: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);
    }
}

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

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

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

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 } 是一个类,而不是一个结构。请注意我如何使用具有正确参数类型的其他 public 方法 - 我同时实现MyType

答案 1 :(得分:1)

C#通常不允许在null上调用方法。我认为编写该程序员的程序员要么来自C ++背景(我认为方法可以在null上调用,只要他们不访问this的数据成员)或写作对于特殊情况(例如通过反思调用,如已经说过的那样)的防御性。