私はC#の経験はありませんが、私が知る限り、メンバー関数内でこれをnullにすることはできません(少なくともこれは、私が知っている言語であるC++とJavaに当てはまります)
あなたの発言が間違っていることに注意することから始めましょう。
C++ では、null レシーバーでメソッドをディスパッチすることは未定義の動作であり、未定義の動作は何でも起こり得ることを意味します。「何でも」には、何も問題がなかったかのように通過NULL
しthis
、継続するプログラムが含まれます。もちろんthis
、C++ で が nullかどうかをチェックするのはややばかげています。これは、プログラムの動作が定義されていないため、プログラムが何を行っているかを既に知らない場合にのみチェックが true になる可能性があるためです。
this
Javaでnullにできるかどうかはわかりません。
ここで、C# に関する質問に答えます。過負荷ではないと仮定しましょう==
。この点については後で説明します。
メソッドは C# で記述されています。null レシーバーを使用して C# プログラムから呼び出されたとします。C# コンパイラは、レシーバーが null になる可能性があるかどうかを評価します。null の可能性がある場合は、メソッドを呼び出す前に null チェックを行うコードを生成するようにします。したがって、このチェックはそのシナリオでは無意味です。もちろん、これは 99.9999% の可能性があるシナリオです。
mike z's answer のように、リフレクションを介して呼び出されたとします。その場合、呼び出しを実行しているのは C# 言語ではありません。むしろ、誰かが反射を意図的に悪用しています。
別の言語から呼び出されたとします。仮想メソッドがあります。仮想ディスパッチを使用してこの他の言語から呼び出された場合、null チェックを実行する必要があります。なぜなら、仮想スロットにあるものを他にどのように知ることができるでしょうか? そのシナリオでは、null にすることはできません。
しかし、非仮想ディスパッチを使用して別の言語から呼び出されたとします。その場合、他の言語は null をチェックする C# 機能を実装する必要はありません。それを呼び出して null を渡すだけです。
したがって、C# にはいくつかの方法がありますthis
がnull
、それらはすべて主流から外れています。したがって、教授のようにコードを書く人は非常にまれです。C# プログラマーは慣用的に、そうでthis
はないnull
と想定し、チェックすることはありません。
邪魔にならないようになったので、そのコードをもう少し批判しましょう。
public override bool Equals(object o) {
if (o == null)
return (this == null);
else {
return ((o is Person) && (this.dni == (o as Person).dni));
}
}
まず、明らかなバグがあります。これは null の可能性があると思いthis
ます。よし、それで実行しましょう。 null参照例外のスローを停止するものは何ですかthis.dni
??? それが null になる可能性があると想定する場合はthis
、少なくとも一貫してそうしてください! (Coverity では、この種の状況を「前方ヌル欠陥」と呼んでいます。)
次:おそらく参照の等価性を意味するために、オーバーライドEquals
してから inside を使用しています。この方法は狂気です!これで、 trueでも falseにもなり得る状況が発生しました。これは恐ろしいです。そこに行かないでください。オーバーライドする場合は、同時にオーバーロードし、その間に実装します。 ==
x.Equals(y)
x==y
Equals
==
IEquatable<T>
(ここで、狂気はどちらの方向にもあるという合理的な議論があります。が値セマンティクス==
と一致している場合、 は とは異なる可能性があります。これも奇妙に思えます。ここでのポイントは、C# では等価性がかなり混乱しているということです。)Equals
personx == persony
(object)personx == (object)persony
さらに、==
後でオーバーライドされた場合はどうなりますか? コードの作成者が明らかに参照比較を行いたい場合、Equals
オーバーライドされた演算子を呼び出すようになりました。==
これはバグのレシピです。
私の推奨事項は、(1) 正しいことを行う静的メソッドを 1 つ作成すること、および (2)ReferenceEquals
等価性の意味について混乱が生じる可能性がある場合は常に使用することです。
private static bool Equals(Person x, Person y)
{
if (ReferenceEquals(x, y))
return true;
else if (ReferenceEquals(x, null))
return false;
else if (ReferenceEquals(y, null))
return false;
else
return x.dni == y.dni;
}
それはすべてのケースをうまくカバーします。参照等価セマンティクスが意図されている場合、読者にとって非常に明確であることに注意してください。また、このコードにより、デバッグの目的で、それぞれの可能性にブレークポイントを簡単に設定できることに注意してください。そして最後に、できるだけ安いものを早い段階で取っていることに注意してください。オブジェクトが等しい参照である場合、コストがかかる可能性のあるフィールドの比較を行う必要はありません!
他の方法は簡単です。
public static bool operator ==(Person x, Person y)
{
return Equals(x, y);
}
public static bool operator !=(Person x, Person y)
{
return !Equals(x, y);
}
public override bool Equals(object y)
{
return Equals(this, y as Person);
}
public bool Equals(Person y)
{
return Equals(this, y);
}
あなたの教授の方法よりも、私の方法の方がはるかにエレガントで明快であることに注目してください。また、私のやり方ではnull と直接this
比較することなくnull を処理していることに注意してください。this
繰り返しますが、これはすべて、値と参照の両方の等価性が可能であり、等価性を実装する4 つの ( ==
、!=
、object.Equals(object)
および) 方法があるという妥協点に到達したことを示しています。IEquatable<T>.Equals(T)
this
null
このテーマに興味がある方は、今週のブログで少し難しい問題について説明します。それは、不等式を含む一般的な比較を実装する方法です。
http://ericlippert.com/2013/10/07/math-from-scratch-part-six-comparisons/
コメントは、C# がどのように等価性を処理するかについての批評として特に興味深いものです。
最後に: override を忘れないでくださいGetHashCode
。 正しく行うようにしてください。