你为什么要使用String.Equals而不是==?

时间:2009-11-02 01:55:25

标签: c# string equals

我最近介绍了一个大型代码库,并注意到所有字符串比较都是使用String.Equals()代替==

完成的

你觉得这是什么原因?

8 个答案:

答案 0 :(得分:297)

很可能很大一部分开发人员来自Java背景,使用==比较字符串是错误的,不起作用。

在C#中,只要键入字符串,就没有(实际)差异(对于字符串)。

如果输入的内容为objectT,请在此处查看其他答案,了解泛型方法或运算符重载,因为您肯定要使用Equals方法。

答案 1 :(得分:90)

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#}

objstr2str4obj2引用相同。

objobj2object type,其他为string type

<强> Conclusion

  1. com1 :result =(obj == str2); // true
    • 比较objectstring,因此执行参考等式检查
    • obj和str2指向相同的引用,因此结果为真
  2. com2 :result =(obj == str3); // false
    • 比较objectstring,因此执行参考等式检查
    • obj和str3指向不同的引用,因此结果为false
  3. com3 :result =(obj == str4); // true
    • 比较objectstring,因此执行参考等式检查
    • obj和str4指向相同的引用,因此结果为真
  4. com4 :result =(str2 == str3); // true
    • 比较stringstring,因此执行字符串值检查
    • str2和str3都是“String”,因此结果为真
  5. com5 :result =(str2 == str4); // true
    • 比较stringstring,因此执行字符串值检查
    • str2和str4都是“String”,因此结果为真
  6. com6 :result =(str3 == str4); // true
    • 比较stringstring,因此执行字符串值检查
    • str3和str4都是“String”,因此结果为真
  7. com7 :result =(obj == obj2); // false - 比较objectobject,以便执行引用相等性检查 - obj和obj2指向不同的引用,因此结果为false

答案 2 :(得分:64)

==和String.Equals方法之间存在一个微妙但非常重要的差异

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

您可以看到==运算符将 false 返回到两个明显相等的字符串。为什么?因为泛型方法中使用的==运算符被解析为System.Object定义的op_equal方法(方法在编译时具有的唯一保证),这意味着它是引用相等而不是值相等。 / p>

如果有两个值显式地键入System.String,则==具有值等于语义,因为编译器将==解析为System.String.op_equal而不是System.Object.op_equal。

所以为了安全起见,我几乎总是使用String.Equals代替我总是得到我想要的值相等语义。

如果其中一个值为null,为了避免NullReferenceExceptions,我总是使用 static String.Equals方法:

bool true = String.Equals("a", "ba".Substring(1));

答案 3 :(得分:36)

String.Equals确实提供了重载来处理大小写和文化感知的比较。如果您的代码没有使用这些代码,那么开发人员可能只会习惯使用Java,其中(如Matthew所说),您必须使用.Equals方法进行内容比较。

答案 4 :(得分:19)

两种方法在功能上执行相同的操作 - 它们比较
正如MSDN上所写:

但是如果你的一个字符串实例为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");

答案 5 :(得分:16)

this article上有一篇文章,你可能会发现它很有趣,Jon Skeet引用了一些文章。似乎使用情况几乎相同。

  

Jon Skeet声称当字符串很短时,实例Equals“的性能会稍微好一些 - 因为字符串的长度增加,差异变得完全无关紧要。”

答案 6 :(得分:5)

我想补充说还有另一个区别。这与安德鲁发布的内容有关。

这也与在我们的软件中发现错误非常烦人有关。请参阅以下简化示例(我也省略了空检查)。

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。你失去了一点类型安全性。

答案 7 :(得分:4)

我一直在试图解决一个错误的墙上碰到我的头,因为我读了这个页面并得出结论,在实践中没有任何有意义的差异所以我会在这里发布这个链接以防其他人发现他们从==和等于得到不同的结果。

Object == equality fails, but .Equals succeeds. Does this make sense?

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