.NETのオブジェクトクラスに2つのオーバーロードがあるのはなぜですか?Equals
たとえば、セットまたはディクショナリを使用できるように、カスタムの等式関数が必要な場合は、(に加えてGetHashCode
)両方をオーバーライドする必要があります。または、どちらか一方だけをオーバーライドするだけで十分です。
3 に答える
静的バージョンをオーバーライドすることはできません。
object.Equals(myObject, myOtherObject)
静的バージョンの理由は、事前にnullをチェックせずに呼び出すことができるようにするためです。
内部的には、nullをチェックし(true
両方のオブジェクトがnullの場合は戻ります)、次にに委任しmyObject.Equals(myOtherObject)
ます。したがって、必要なのは非静的Equalsメソッドをオーバーライドすることだけです。
静的メソッドをオーバーライドすることはできません。
非静的メソッドのみをオーバーライドすれば問題ありません...
この記事を読む: 方法:静的メソッドをオーバーライドする:
静的メンバーをオーバーライドできないのはなぜですか?
ほんとに?なんで?あなたがそれについて考えるならば、これはただの常識です。通常の(インスタンス)メンバーをオーバーライドするには、仮想ディスパッチメカニズムを使用して、コントラクトを実装から分離します。コントラクトはコンパイル時に認識されますが(インスタンスメンバーの署名)、実装は実行時にのみ認識されます(具体的なタイプのオブジェクトは具体的な実装を提供します)。コンパイル時の実装の具体的なタイプはわかりません。
これは理解しておくべき重要なことです。型が他の型から継承する場合、それらは共通のコントラクトを満たしますが、静的型は(純粋なOOPの観点から)どのコントラクトにも拘束されません。この言語には、2つの静的型を「継承」コントラクトと結び付ける技術的な方法はありません。2つの異なる場所でLogメソッドを「オーバーライド」する場合、ここでどちらを呼び出しているかをどのようにして知ることができますか。Log.Message( "実装は何ですか?")
静的メンバーでは、それらが定義されているタイプを明示的に指定することによってそれらを呼び出します。つまり、実装を直接呼び出すことになりますが、これも契約に拘束されません。
ちなみに、静的メンバーがインターフェースを実装できないのはそのためです。そのため、ここでは仮想ディスパッチは役に立ちません。すべてのクライアントは、契約なしで実装を直接呼び出します。
「最初の」オブジェクトがnullの場合、静的メソッドが存在します。たとえば、a
がnullでnullb
でない場合、実行することはできませんが、を実行するa.Equals(b)
ことはできますobject.Equals(a, b)
。
2つの理由から、インスタンスメソッドのみをオーバーライドする必要があります(そしてオーバーライドできます)。まず、静的メソッドをオーバーライドすることはできません。次に、静的メソッドは最終的に非静的メソッドを呼び出します。
詳細については、ドキュメントを参照してください。