質問
2つの文字列を比較するシルバーライトアプリケーションの条件があります。何らかの理由で ==
を使用すると、 .Equals()
は true を返します。
コードは次のとおりです:
if (((ListBoxItem)lstBaseMenu.SelectedItem).Content.Equals("Energy Attack"))
{
// Execute code
}
if (((ListBoxItem)lstBaseMenu.SelectedItem).Content == "Energy Attack")
{
// Execute code
}
これが起こっている理由について何か理由はありますか?
解決
==
がタイプ object
の式で使用される場合、 System.Object.ReferenceEquals
。
等しい
は< code> virtual メソッドとそのように動作するため、オーバーライドされたバージョンが使用されます( string
タイプの場合は内容を比較します)。
他のヒント
オブジェクト参照を文字列と比較する場合(オブジェクト参照が文字列を参照する場合でも)、文字列クラス固有の ==
演算子の特別な動作は無視されます。
通常(つまり、文字列を処理しない場合)、 Equals
は values を比較し、 ==
はオブジェクト参照。
比較している2つのオブジェクトがオブジェクトのまったく同じインスタンスを参照している場合、両方がtrueを返しますが、一方が同じコンテンツを持ち、異なるソースから来た場合(同じデータを持つ別のインスタンス)、Equalsのみが返されますtrueを返します。ただし、コメントに記載されているように、stringは ==
演算子をオーバーライドするため、文字列は特別なケースです。したがって、純粋に文字列参照(オブジェクト参照ではない)を処理する場合、値だけが比較されても別のインスタンスです。次のコードは、動作のわずかな違いを示しています。
string s1 = "test";
string s2 = "test";
string s3 = "test1".Substring(0, 4);
object s4 = s3;
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s2), s1 == s2, s1.Equals(s2));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s3), s1 == s3, s1.Equals(s3));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s4), s1 == s4, s1.Equals(s4));
出力は次のとおりです。
True True True
False True True
False False True
==
および .Equals
は両方とも、実際のタイプと呼び出しサイトでの実際のタイプで定義された動作に依存します。どちらもメソッド/演算子であり、任意の型でオーバーライドでき、作成者が望む動作を指定できます。私の経験では、オブジェクトに .Equals
を実装することは一般的ですが、演算子 ==
を実装することを怠ることがよくあります。つまり、 .Equals
は実際に値の等価性を測定し、 ==
は同じ参照であるかどうかを測定します。
定義が流動的である、または汎用アルゴリズムを記述する新しいタイプを使用している場合、ベストプラクティスは次のとおりです
- C#で参照を比較する場合は、
Object.ReferenceEquals
を直接使用します(汎用の場合は不要です) - 値を比較する場合は、
EqualityComparer&lt; T&gt; .Default
を使用します
==
の使用法が曖昧だと感じる場合、曖昧さを取り除くためにコードで Object.Reference
を明示的に使用します。
Eric Lippertは最近、CLRに平等の2つの方法がある理由に関するブログ投稿を行いました。読む価値はあります
まず、違いがあります 。数字の場合
> 2 == 2.0
True
> 2.Equals(2.0)
False
そして文字列用
> string x = null;
> x == null
True
> x.Equals(null)
NullReferenceException
どちらの場合も、 ==
は .Equals
オブジェクトを文字列にキャストすると、正しく動作することを追加します。これが、コンパイラが次のような警告を表示する理由です。
意図しない参照比較の可能性。値の比較を取得するには、 左側をキャストして「string」と入力します
==演算子 1.オペランドが値の種類であり、それらの値が等しい場合、戻りますtrueまたはfalse。 2.オペランドが参照タイプで、文字列を除き、両方が参照する場合同じオブジェクト、trueまたはfalseを返します。 3.オペランドが文字列型で値が等しい場合、trueまたはfalseを返します。
。等しい 1.オペランドが参照タイプの場合、参照の平等つまり、両方が同じオブジェクトを参照している場合はtrueを返し、そうでない場合はfalseを返します。 2.オペランドが値型の場合、==演算子とは異なり、最初に型をチェックし、型が同じ場合は==演算子を実行し、そうでない場合はfalseを返します。
私が理解している限り、答えは簡単です:
- ==オブジェクト参照を比較します。
- .Equalsはオブジェクトの内容を比較します。
- 文字列データ型は常にコンテンツ比較のように機能します。
私が正しいこと、そしてあなたの質問に答えてくれることを願っています。
.Equal
メソッドの静的バージョンはこれまで言及されていなかったため、3つのバリエーションをまとめて比較するためにここに追加したいと思います。
MyString.Equals("Somestring")) //Method 1
MyString == "Somestring" //Method 2
String.Equals("Somestring", MyString); //Method 3 (static String.Equals method) - better
where MyString
は、コード内のどこかから来た変数です。
背景情報とサマライズ:
Javaで ==
を使用して文字列を比較することは使用しないでください。両方の言語を使用する必要がある場合と、また
==
を使用することもC#でより良いものに置き換えることができることをお知らせします。
C#では、両方が文字列型である限り、方法1または方法2を使用して文字列を比較するのに実際的な違いはありません。ただし、1つがnullの場合、1つが別のタイプ(整数など)、または1つが異なる参照を持つオブジェクトを表す場合、最初の質問が示すように、等しいかどうかのコンテンツを比較しても何が返されないことがあります期待します。
推奨されるソリューション:
==
を使用することは、物事を比較するときに .Equals
を使用することとまったく同じではないため、 static String.Equals メソッドを使用できます。代わりに。この方法では、2つの側が同じタイプではない場合でもコンテンツを比較し、片方がnullである場合は例外を回避します。
bool areEqual = String.Equals("Somestring", MyString);
書くのはもう少しですが、私の意見では、使用する方が安全です。
Microsoftからコピーした情報を次に示します。
public static bool Equals (string a, string b);
パラメータ
a
文字列
比較する最初の文字列、または null
。
b
文字列
比較する2番目の文字列、または null
。
Boolean
a
の値が b
の値と同じ場合、 true
。それ以外の場合は、 false
。 a
と b
の両方が null
の場合、メソッドは true
を返します。
ここで少し混乱しています。コンテンツのランタイムタイプが文字列タイプの場合、==とEqualsの両方がtrueを返す必要があります。ただし、これはそうではないように見えるため、コンテンツのランタイムタイプは文字列ではなく、その上でEqualsを呼び出すことは参照等価を実行し、これはEquals(&quot; Energy Attack&quot;)が失敗する理由を説明します。ただし、2番目のケースでは、どのオーバーロード==静的演算子を呼び出すかに関する決定はコンパイル時に行われ、この決定は==(string、string)のように見えます。これは、Contentが文字列への暗黙的な変換を提供していることを示唆しています。
@BlueMonkMNによる以前の回答には別の側面があります。追加の次元は、@ Drahcirのタイトルの質問に対する答えは、説明されているように、 string
値に到達した方法にも依存するということです。説明する:
string s1 = "test";
string s2 = "test";
string s3 = "test1".Substring(0, 4);
object s4 = s3;
string s5 = "te" + "st";
object s6 = s5;
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s2), s1 == s2, s1.Equals(s2));
Console.WriteLine("\n Case1 - A method changes the value:");
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s3), s1 == s3, s1.Equals(s3));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s4), s1 == s4, s1.Equals(s4));
Console.WriteLine("\n Case2 - Having only literals allows to arrive at a literal:");
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s5), s1 == s5, s1.Equals(s5));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s6), s1 == s6, s1.Equals(s6));
出力は次のとおりです。
True True True
Case1 - A method changes the value:
False True True
False False True
Case2 - Having only literals allows to arrive at a literal:
True True True
True True True
答えにもう1点追加します。
.EqualsTo()
メソッドを使用すると、文化や大文字と小文字を区別して比較することができます。
C#の ==
トークンは、2つの異なる等価チェック演算子に使用されます。コンパイラはそのトークンに遭遇すると、比較されている特定の組み合わせタイプ(*)、または両方のタイプを変換できるタイプの組み合わせに対して、比較されているタイプのいずれかが等価演算子オーバーロードを実装しているかどうかをチェックします。コンパイラーがそのようなオーバーロードを見つけると、それを使用します。それ以外の場合、2つの型が両方とも参照型であり、それらが無関係なクラス(インターフェイスまたは関連クラスのいずれか)でない場合、コンパイラは ==
を参照比較演算子と見なします。どちらの条件も当てはまらない場合、コンパイルは失敗します。
他の言語では、2つの等価性チェック演算子に個別のトークンを使用していることに注意してください。たとえば、VB.NETでは、 =
トークンは式内でオーバーロード可能な等価性チェック演算子のみに使用され、 Is
は参照テストまたはnull-テスト演算子。参照チェックの等価性または無効性のテスト以外の目的で Is
を使用しようとすると、等価チェック演算子をオーバーライドしない型で =
を使用すると失敗します。
(*)タイプは通常、それ自体との比較のために等値をオーバーロードするだけですが、タイプが他の特定のタイプとの比較のために等値演算子をオーバーロードすると便利な場合があります。たとえば、 int
は float
との比較のために等値演算子を定義できますが(そうではありません)、16777217は16777216fに等しいと報告しません。現状では、このような演算子は定義されていないため、C#は int
を float
に昇格させ、等価チェック演算子が認識する前に16777216fに丸めます。その演算子は、2つの等しい浮動小数点数を確認し、それらが等しいと報告します。発生した丸めは認識されません。
本当に素晴らしい答えと例!
2つの基本的な違いを追加したいだけです
です
==
などの演算子はポリモーフィックではありませんが、Equals
は
その概念を念頭に置いて、(左手と右手の参照型を見て、型に実際に==演算子がオーバーロードされており、Equalsがオーバーライドされているかどうかを確認することで)例を実行すると、確実に取得できます正しい答え。
オブジェクトを作成するとき、オブジェクトには2つの部分があり、一方はコンテンツで、もう一方はそのコンテンツへの参照です。
==
は、コンテンツと参照の両方を比較します。
equals()
はコンテンツのみを比較します
http:// www。 codeproject.com/Articles/584128/What-is-the-difference-between-equalsequals-and-Eq
==
==演算子を使用して、任意の種類の2つの変数を比較できます。単純にビットを比較します。
int a = 3;
byte b = 3;
if (a == b) { // true }
注:intの左側にはさらにゼロがありますが、ここでは気にしません。
int a(00000011)== byte b(00000011)
Remember ==演算子は、変数内のビットのパターンのみを考慮します。
Use == 2つの参照(プリミティブ)がヒープ上の同じオブジェクトを参照する場合。
変数が参照であろうとプリミティブであろうと、ルールは同じです。
Foo a = new Foo();
Foo b = new Foo();
Foo c = a;
if (a == b) { // false }
if (a == c) { // true }
if (b == c) { // false }
a == cはtrue a == bはfalse
ビットパターンはaとcで同じであるため、==を使用して等しくなります。
等しい():
equals()メソッドを使用して、 2つの異なるオブジェクトが等しいかどうかを確認します。
&quot; Jane&quot;の文字を表す2つの異なるStringオブジェクトなど
Equalと==の唯一の違いは、オブジェクトタイプの比較です。参照型や値型などのその他の場合、それらはほぼ同じです(両方ともビット単位で等しいか、両方とも参照で等しい)。
オブジェクト: 等しい:ビット単位の等式 ==:参照平等
string:(stringの等しいおよび==は同じですが、stringの1つがobjectに変更された場合、比較結果は異なります) 等しい:ビット単位の等式 ==:ビットごとの同等性
詳細については、こちらをご覧ください。