2

考虑一下我正在查看的以下代码:

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可以为空。我坚持认为它不能(除非有人使用直接内存操作)。我们应该把它留在里面吗?

4

2 回答 2

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调用空目标上的实例方法的 IL。完全合法,只是 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
}

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

于 2013-01-30T21:10:19.033 回答
1

C# 通常不允许在null. 我认为编写该代码的程序员要么来自 C++ 背景(我认为可以调用方法null,只要它们不访问 的数据成员this)要么为特殊场景(例如通过反射调用)进行防御性编写,正如已经说过的)。

于 2013-01-30T21:14:28.240 回答