翻訳者から:
これは、以前はC#開発者の1人であったEric Lippertのブログ 投稿の無料翻訳です。 記録は「質問と回答」の形式です。質問をスキップして回答に進みます。元の質問に慣れることができますが、特に興味深いものはありません。
ただし、まずは次のコードをご覧ください。Googleとコンパイルを行わずに、比較の9つのケースで何が起こるかを調べ、回答を確認してください(アンケートの場合)。
int myInt = 1; short myShort = 1; object objInt1 = myInt; object objInt2 = myInt; object objShort = myShort; Console.WriteLine(myInt == myShort);
C#言語は、開発者が期待するとおりに動作するように設計されています。つまり、
明らかなテクニックと
正しいテクニックがまったく同じ言語です。 そして大部分はそうです。 残念ながら、比較はトラップのある言語の一部です。
次のコードを作成して、さまざまな程度の比較を示します。
答え int myInt = 1; short myShort = 1; object objInt1 = myInt; object objInt2 = myInt; object objShort = myShort; Console.WriteLine(myInt == myShort);
一体何? 順番に見てみましょう。
最初のケースと
2番目のケースでは、
最初に ==
演算子の意味を決定する必要があります。 C#には、さまざまな型を比較するための十数個の組み込み
==
演算子があります。
object == object string == string int == int uint == uint long == long ulong == ulong ...
int == short
または
short == int
演算子がないため、最適な演算子を選択する必要があります。 私たちの場合、これは
int == int
ステートメントです。 したがって、
short
int
変換され、2つの変数が値で比較されます。 したがって、それらは同等です。
3番目の場合、オーバーロードされたEqualsメソッドのどれを呼び出すかを最初に決定する必要があります。 呼び出し元のインスタンスは
int
型であり、3つの
Equals
メソッドを実装しています。
Equals(object, object)
前者は、それを呼び出すのに十分な引数がないため、私たちには適していません。 他の2つのメソッドの中で、パラメーターとして
int
を受け入れるメソッドの方が適しています;常に
short
型の引数を
object
に変換するよりも
int
に変換する方が適切です。 したがって、値による比較を使用して
int
型の2つの変数を比較する
Equals(int)
が呼び出されるため、この式はtrueです。
4番目のケースでは、どの
Equals
メソッドが呼び出されるかを再度決定する必要があります。 呼び出し元のインスタンスの型は
short
、これには3つの
Equals
メソッドがあります。
Equals(object, object)
最初のメソッドと3番目のメソッドは、引数が少なすぎるため、適切ではありません。また、
int
型の
short
への暗黙的なキャストがないため、3番目のメソッドは選択されません。
short.Equals(object)
メソッドが残り、その実装は次のコードと同じです。
bool Equals(object z) { return z is short && (short)z == this; }
つまり、このメソッドが
true
を返すためには、
パッケージ化された要素は
short
型である必要があり、展開後は
Equals
を呼び出したインスタンスと等しくなければなりません。 ただし、渡された引数は
int
であるため、メソッドは
false
を返し
false
。
5番目 、
6番目 、
7番目では、
object == object
比較フォームが選択されます。これは、
Object.ReferenceEquals
メソッドを呼び出すのと
Object.ReferenceEquals
です。 明らかに、2つのリンクは
5番目のケースでは等しく、
6番目と
7 番目のケースでは等しくありません。 タイプ
object
変数に含まれる値
object
重要で
object
ません。値による比較はまったく使用されず、リンクのみが比較されるためです。
8番目と
9番目のケースでは、静的メソッド
Object.Equals
が使用され、次のように実装されます。
public static bool Equals(object x, object y) { if (ReferenceEquals(x, y)) return true; if (ReferenceEquals(x, null)) return false; if (ReferenceEquals(y, null)) return false; return x.Equals(y); }
8番目のケースでは、
null
と等しくない2つのリンクがあるため、
int.Equals(object)
が呼び出されます。これは、
short.Equals(object)
メソッドのコードを見ればわかるように、次のように実装されます。
bool Equals(object z) { return z is int && (int)z == this; }
引数は
int
型のパック変数であるため、値によって比較が行われ、メソッドは
true
を返し
true
。
9番目のケースでは、パック変数の型は
short
であるため、型のチェック(
z is int
)は失敗し、メソッドは
false
を返し
false
。
結果 :
2つの変数を比較するための9つの異なる方法を示しましたが、すべての場合において、比較される変数は1に等しく、半分の場合にのみ比較が
true
返し
true
。 これがおかしくて、すべてが混乱していると思うなら、あなたは正しいです! C#での比較は非常に潜行的です。