简体   繁体   English

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

[英]Why would I ever want to do object.ReferenceEquals(null, this) in Equals override?

Consider the following code that I was reviewing: 请考虑以下我正在审核的代码:

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

The first line in this code triggered my curiosity. 这段代码的第一行引发了我的好奇心。 Whenever this is null, the method should return false. 只要this为null,该方法应返回false。 Now I am pretty sure the programmer meant to write !object.ReferenceEquals(other, null) , to shortcut situations with null , but he's insistent that this can be null. 现在我非常确定程序员打算写一个!object.ReferenceEquals(other, null) ,以使用null来快捷方式,但他坚持认为this可以为null。 I'm insistent that it cannot (unless someone uses direct memory manipulation). 我坚持认为它不能(除非有人使用直接内存操作)。 Should we leave it in? 我们应该留下吗?

While I certainly wouldn't normally check this for nullity, it's possible, without any actual memory nastiness - just a bit of reflection: 虽然我肯定不会正常检查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);
    }
}

Alternatively, generate IL which uses call instead of callvirt to call an instance method on a null target. 或者,生成IL,它使用call而不是callvirt来调用null目标上的实例方法。 Entirely legit, just not something the C# compiler would normally do. 完全合法,不是C#编译器通常会做的事情。

This has nothing to do with finalization, which is hairy in its own right but in different ways. 这与终结无关,终结本身就是毛茸茸的,但却以不同的方式。 It's possible for a finalizer to run while an instance method is executing if the CLR can prove that you're not going to use any fields in the instance (which I would strongly expect to include the this reference). 如果CLR可以证明你不会使用实例中的任何字段 (我强烈希望包含this引用) ,那么在实例方法执行时可以运行终结器。

As for the code presented - nope, that looks like it's just a mistake. 至于提供的代码 - 不,这看起来只是一个错误。 I would rewrite it as: 我会把它重写为:

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
}

... assuming that MyType is a class, not a struct. ...假设MyType是一个类,而不是一个结构。 Note how I'm using another public method with the right parameter type - I'd implement IEquatable<MyType> at the same time. 注意我是如何使用具有正确参数类型的另一个公共方法 - 我同时实现IEquatable<MyType>

C# doesn't normally allow methods to be called on null . C#通常不允许在null上调用方法。 I think that the programmer who wrote that is either coming from a C++ background (where I think methods can be called on null , as long as they don't access a data member of this ) or writing defensively for special scenarios (such as invocation by reflection, as has already been said). 我认为这是谁写的,程序员无论是从C ++背景的(这里我认为方法可以被称为null的,只要他们不访问的数据成员this )或写防守特殊情况下(如调用通过反思,正如已经说过的那样)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 object.ReferenceEquals或==运算符? - object.ReferenceEquals or == operator? Object.ReferenceEquals永远不会命中 - Object.ReferenceEquals never hit C#operator ==,StringBuilder.Equals,Object.Equals和Object.ReferenceEquals之间的差异 - C# Differences between operator ==, StringBuilder.Equals, Object.Equals and Object.ReferenceEquals c#中Object.Equals(object,object)和Object.ReferenceEquals(object,object)之间的区别 - difference between Object.Equals(object,object) and Object.ReferenceEquals(object,object) in c# Object.ReferenceEquals对于匹配的字符串返回true - Object.ReferenceEquals returns true for matching strings IEnumerable、Where 和 Object.ReferenceEquals 的问题 - Issue with IEnumerable, Where, and Object.ReferenceEquals Object.ReferenceEquals为两个不同的对象输出true - Object.ReferenceEquals prints true for two different objects &#39;Object.ReferenceEquals&#39;始终为false,因为它使用值类型进行调用 - 'Object.ReferenceEquals' is always false because it is called with a value type Assert.ReferenceEquals()在Visual Studio Test中Object.ReferenceEquals()返回&#39;false&#39;的位置 - Assert.ReferenceEquals() Passes where Object.ReferenceEquals() returns 'false' in Visual Studio Test 在关于 Equals 覆盖的 msdn 指南中,为什么在空检查中强制转换为对象? - In the msdn guidance on Equals override, why the cast to object in the null check?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM