374

String.Equals()私は最近、大規模なコードベースを紹介され、すべての文字列比較が代わりに使用されていることに気付きました==

その理由は何だと思いますか。

4

8 に答える 8

378

開発者ベースの大部分は、==文字列を比較するために使用することが間違っていて機能しない Java のバックグラウンドから来ている可能性が非常に高いです。

C# では、文字列として入力されている限り、(文字列に対して) (実質的な) 違いはありません。

それらが次のように入力されている場合、objectまたはTジェネリックメソッドまたは演算子のオーバーロードについて話している他の回答をここで見る場合は、間違いなく Equals メソッドを使用する必要があります。

于 2009-11-02T01:58:45.653 に答える
124

と の間には実質的な違いがstring.Equalsあります==

bool result = false;

object obj = "String";    
string str2 = "String";
string str3 = typeof(string).Name;
string str4 = "String";
object obj2 = str3;

// Comparision between object obj and string str2 -- Com 1
result = string.Equals(obj, str2);// true
result = String.ReferenceEquals(obj, str2); // true
result = (obj == str2);// true

// Comparision between object obj and string str3 -- Com 2
result = string.Equals(obj, str3);// true
result = String.ReferenceEquals(obj, str3); // false
result = (obj == str3);// false

// Comparision between object obj and string str4 -- Com 3
result = string.Equals(obj, str4);// true
result = String.ReferenceEquals(obj, str4); // true
result = (obj == str4);// true

// Comparision between string str2 and string str3 -- Com 4
result = string.Equals(str2, str3);// true
result = String.ReferenceEquals(str2, str3); // false
result = (str2 == str3);// true

// Comparision between string str2 and string str4 -- Com 5
result = string.Equals(str2, str4);// true
result = String.ReferenceEquals(str2, str4); // true
result = (str2 == str4);// true

// Comparision between string str3 and string str4 -- Com 6
result = string.Equals(str3, str4);// true
result = String.ReferenceEquals(str3, str4); // false
result = (str3 == str4);// true

// Comparision between object obj and object obj2 -- Com 7
result = String.Equals(obj, obj2);// true
result = String.ReferenceEquals(obj, obj2); // false
result = (obj == obj2);// false

ウォッチの追加

obj     "String" {1#}   object {string}
str2    "String" {1#}   string
str3    "String" {5#}   string
str4    "String" {1#}   string
obj2    "String" {5#}   object {string}

今見て{1#}{5#}

objstr2str4およびobj2リファレンスは同じです。

objそして、他の人obj2object typestring type

結論

  1. com1 : 結果 = (obj == str2);// true
    • 比較objectstringて、参照の等価性チェックを実行します
    • obj と str2 は同じ参照を指しているため、結果は true です
  2. com2 : 結果 = (obj == str3);// false
    • 比較objectstringて、参照の等価性チェックを実行します
    • obj と str3 は異なる参照を指しているため、結果は false です
  3. com3 : 結果 = (obj == str4);// true
    • 比較objectstringて、参照の等価性チェックを実行します
    • obj と str4 は同じ参照を指しているため、結果は true です
  4. com4 : 結果 = (str2 == str3);// true
    • 比較stringstringて、文字列値チェックを実行します
    • str2 と str3 はどちらも「文字列」なので、結果は true です
  5. com5 : 結果 = (str2 == str4);// true
    • 比較stringstringて、文字列値チェックを実行します
    • str2 と str4 はどちらも「文字列」なので、結果は true です
  6. com6 : 結果 = (str3 == str4);// true
    • 比較stringstringて、文字列値チェックを実行します
    • str3 と str4 はどちらも「文字列」なので、結果は true です
  7. com7 : result = (obj == obj2);// false - 比較objectobject、参照の等価性チェックを実行します - obj と obj2 は異なる参照を指しているため、結果は false です
于 2013-02-26T13:37:31.693 に答える
90

== メソッドと String.Equals メソッドの間には、微妙ではあるが非常に重要な違いが 1 つあります。

class Program
{
    static void Main(string[] args)
    {
        CheckEquality("a", "a");
        Console.WriteLine("----------");
        CheckEquality("a", "ba".Substring(1));
    }

    static void CheckEquality<T>(T value1, T value2) where T : class
    {
        Console.WriteLine("value1: {0}", value1);
        Console.WriteLine("value2: {0}", value2);

        Console.WriteLine("value1 == value2:      {0}", value1 == value2);
        Console.WriteLine("value1.Equals(value2): {0}", value1.Equals(value2));

        if (typeof(T).IsEquivalentTo(typeof(string)))
        {
            string string1 = (string)(object)value1;
            string string2 = (string)(object)value2;
            Console.WriteLine("string1 == string2:    {0}", string1 == string2);
        }
    }
}

次の出力が生成されます。

value1: a
value2: a
value1 == value2:      True
value1.Equals(value2): True
string1 == string2:    True
----------
value1: a
value2: a
value1 == value2:      False
value1.Equals(value2): True
string1 == string2:    True

== 演算子が明らかに等しい 2 つの文字列に対してfalseを返していることがわかります。なんで?ジェネリック メソッドで使用されている == 演算子は、System.Object で定義されている op_equal メソッドに解決されるため (メソッドがコンパイル時に持つ T の唯一の保証)、値の等価性ではなく参照の等価性であることを意味します。

System.String として明示的に型指定された 2 つの値がある場合、コンパイラは == を System.Object.op_equal ではなく System.String.op_equal に解決するため、== は値が等しいセマンティックを持ちます。

したがって、安全にプレイするために、ほとんどの場合、代わりに String.Equals を使用して、必要な値の等価セマンティクスを常に取得します。

また、値の 1 つが null の場合に NullReferenceExceptions を回避するために、私は常に静的なString.Equals メソッドを使用します。

bool true = String.Equals("a", "ba".Substring(1));
于 2013-09-30T19:51:12.093 に答える
46

String.Equalsは、ケーシングとカルチャを考慮した比較を処理するためのオーバーロードを提供します。コードでこれらを使用しない場合、開発者は Java に慣れているだけかもしれません。(マシューが言うように) .Equals メソッドを使用して内容を比較する必要があります。

于 2009-11-02T02:01:13.317 に答える
36

どちらの方法も機能的には同じです。を比較します。
MSDNに書かれているように:

  • メソッドについてString.Equals-このインスタンスと別の指定されたStringオブジェクトが同じ値を持っているかどうかを判別します。(http://msdn.microsoft.com/en-us/library/858x0yyx.aspx
  • 概要==-文字列は参照型ですが、等価演算子(==および !=)は、参照ではなく文字列オブジェクトの値を比較するために定義されています。これにより、文字列の同等性のテストがより直感的になります。(http://msdn.microsoft.com/en-en/library/362314fe.aspx

ただし、文字列インスタンスの1つがnullの場合、これらのメソッドの動作は異なります。

string x = null;
string y = "qq";
if (x == y) // returns false
    MessageBox.Show("true");
else
    MessageBox.Show("false");

if (x.Equals(y)) // returns System.NullReferenceException: Object reference not set to an instance of an object. - because x is null !!!
    MessageBox.Show("true");
else
    MessageBox.Show("false");
于 2012-04-12T11:35:53.113 に答える
16

この記事には興味深い記事があり、Jon Skeet からの引用がいくつかあります。使用感はほとんど変わらないようです。

Jon Skeet は、インスタンス Equals のパフォーマンスは「文字列が短い場合にわずかに良くなります。文字列が長くなると、その差はまったく重要ではなくなります」と述べています。

于 2009-11-02T01:58:21.207 に答える
8

別の違いがあることを付け加えたいと思います。Andrewの投稿に関連しています。

また、ソフトウェアのバグを見つけるのが非常に面倒なことにも関係しています。次の簡略化された例を参照してください(ヌルチェックも省略しました)。

public const int SPECIAL_NUMBER = 213;

public bool IsSpecialNumberEntered(string numberTextBoxTextValue)
{
    return numberTextBoxTextValue.Equals(SPECIAL_NUMBER)
}

これはコンパイルされ、常に。を返しfalseます。以下はコンパイルエラーを出しますが:

public const int SPECIAL_NUMBER = 213;

public bool IsSpecialNumberEntered(string numberTextBoxTextValue)
{
    return (numberTextBoxTextValue == SPECIAL_NUMBER);
}

誰かがを使用して異なるタイプの列挙型を比較す​​るという同様の問題を解決する必要がありましたEquals。これがバグの原因であることに気付く前に、これを何度も読んでください。特にの定義がSPECIAL_NUMBER問題領域の近くにない場合。

これが、必要のない状況でのEqualsの使用に本当に反対している理由です。型安全性が少し失われます。

于 2012-10-15T12:57:15.587 に答える
5

このページを読んで、実際には意味のある違いはないと結論付けたので、バグを解決しようと壁に頭をぶつけたところです。他の誰かが異なる結果を見つけた場合に備えて、このリンクをここに投稿します==からと等しい。

Object ==等式は失敗しますが、.Equalsは成功します。これは意味がありますか?

string a = "x";
string b = new String(new []{'x'});

Console.WriteLine("x == x " + (a == b));//True
Console.WriteLine("object x == x " + ((object)a == (object)b));//False
Console.WriteLine("x equals x " + (a.Equals(b)));//True
Console.WriteLine("object x equals x " + (((object)a).Equals((object)b)));//True
于 2012-10-12T14:08:58.903 に答える