翻訳者から:
これは、以前は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#での比較は非常に潜行的です。