2

私がレビューしていた次のコードを検討してください。

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

このコードの最初の行が私の好奇心を刺激しました。が null の場合は常にthis、メソッドは false を返す必要があります。!object.ReferenceEquals(other, null)これで、プログラマーは, を使用して状況をショートカットするつもりだったと確信していますが、彼はそれが null になる可能性があるとnull主張しています。this私はそれができないと主張しています(誰かが直接メモリ操作を使用しない限り)。そのままにしておくべきですか?

4

2 に答える 2

7

私は確かに通常はnullをチェック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);
    }
}

または、 nullターゲットでインスタンスメソッドを呼び出すcall代わりにを使用するILを生成します。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
}

MyType...それが構造体ではなくクラスであると仮定します。適切なパラメータタイプで別のパブリックメソッドを使用していることに注意してくださいIEquatable<MyType>。同時に実装します。

于 2013-01-30T21:10:19.033 に答える
1

C# では通常、 でメソッドを呼び出すことはできませんnullnullこれを書いたプログラマーは、C++ のバックグラウンド (のデータ メンバーにアクセスしない限り、 でメソッドを呼び出すことができると思います) から来ているかthis、特別なシナリオ (リフレクションによる呼び出しなど) に対して防御的に書いていると思います。 、すでに述べたように)。

于 2013-01-30T21:14:28.240 に答える