4

演算子を使用すると、次の==ことができます。

int a = 10;
int b = 10;
a==b //true

この場合、C# はコンパイル時に決定を下し、仮想動作は発生しません。

しかし、私が使用する場合:

object a = 10;
object b = 10;
a == b //false

objectはクラス (参照型) でありabそれぞれがヒープ上の異なるボックス化されたオブジェクトを参照しているため、結果は false です。

それを解決するには、次のことを行う必要があります。

object a = 10;
object b = 10;
a.Equals (b) // True

Equalsは仮想メソッドであり、オブジェクトの実際の型に応じて実行時に解決されるためです。

私の質問は:

なぜ C# の設計者は、== を仮想化して問題を回避せず、機能的に Equals と同じにしなかったのでしょうか?

4

3 に答える 3

12

==メソッドであるためstatic、仮想にすることはできません。これはおそらく、より適切に処理するために行われたものnullです。

あなたのジレンマはボクシングとは何の関係もないことに注意してください。C# は両方のパラメーターのコンパイル時の型を使用して、どのオーバーロード* が理に==かなっているのかを判断します。たとえば、次の例を見てください。

object s1 = "Hello";
object s2 = new String('H', 'e', 'l', 'l', 'o');
s1 == s2; //False
(string)s1 == (string)s2; //True

* 複数のクラス階層を検索しているため、オーバーロードは完全に正しいわけではありませんが、議論する上で意味的には十分に近いものです。

于 2012-08-30T17:25:58.577 に答える
2

私が考えることができる理由の 1 つは、== を仮想化すると、継承されたクラスの動作が大幅に予測しにくくなるためです。

class Base {
  public int First;
}

class Derived {
  public int Last;
}

var me = Base{ First = "Alexei" };
var someone = Derived { First = "Alexei", Last = "Unknown" };

現在、ある種の「==」が基本クラスで仮想であり、派生クラスでオーバーライドされていないme == someone場合、これは驚くべきことです。

また、C# が .Net ランタイム用にコードをコンパイルする唯一の言語ではないことも忘れないでください。そのため、同様の概念に対して異なる構文機能を持つ可能性のある他の言語の動作は合理的である必要があります。

于 2012-08-30T17:24:53.477 に答える
1

abが実際に同じオブジェクトであるかどうかを判断するのははるかに難しいからです。私たちはそれを知りたいかもしれません。type の変数を介してそれらを扱っている場合、特にそれを知りたいと思うでしょうobjectobjectID は、 quaの意味のある機能の 1 つですobject。平等の他の定義はそうではありません。

参照型では==EqualsGetHashCodeID のみを参照することから始めます。ReferenceEquals常に ID のみを参照します。

あるタイプの 2 つのオブジェクトが同等であると見なす他の方法を気にする可能性が非常に高い場合Equals、それを利用しGetHashCodeて対応するためにオーバーライドします。

ID を気にする可能性がほとんどない場合は、オーバーライド==も行います。(例: string)。

値の型では==EqualsGetHashCodeフィールドごとの比較について言及します。これは、値の型で論理的な意味を成す、最も差別的な等価性の見方だからです。

object変数を扱うとき、アイデンティティを気にする可能==性は十分Equalsにあります。邪魔にならないものを考えるのは難しいです。

于 2012-08-30T17:37:56.117 に答える