为什么要使用String。等于除以==?

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

你认为这是什么原因?

360331 次浏览

这篇文章上有一篇文章,你可能会觉得很有趣,引用了Jon Skeet的话。看起来用途是差不多的。

Jon Skeet指出,实例Equals的性能“在字符串较短时略好——随着字符串长度的增加,这种差异变得完全不重要。”

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

在c#中,(对于字符串)没有(实际的)区别,只要它们的类型是string

如果它们的类型是objectT,那么在这里可以看到其他关于泛型方法或操作符重载的答案,因为在那里你肯定想使用Equals方法。

String.Equals确实提供了重载来处理区分大小写和区域性的比较。如果您的代码没有使用这些,开发人员可能只是习惯于Java,在那里(正如Matthew所说),您必须使用. equals方法来进行内容比较。

这两个方法都执行相同的功能 -它们比较 正如MSDN上写的:

但如果你的一个字符串实例是空的,这些方法的工作方式是不同的:

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");

我想补充一点,还有一点不同。这与Andrew发布的内容有关。

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

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的定义不在问题区域附近时。

这就是为什么我真的反对在不必要的情况下使用等号。你失去了一点类型安全。

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

结论< a href = " https://stackoverflow.com/questions/15104784/behavior-of-string-equals-and " > < / >:

  1. com1: result = (obj == str2)
    • 比较objectstring,因此执行引用是否相等检查
    • Obj和str2指向相同的引用,因此结果为真
    • 李< / ul > < / >
    • com2: result = (obj == str3)
      • 比较objectstring,因此执行引用是否相等检查
      • Obj和str3指向不同的引用,因此结果为假
      • 李< / ul > < / >
      • com3: result = (obj == str4)
        • 比较objectstring,因此执行引用是否相等检查
        • Obj和str4指向相同的引用,因此结果为真
        • 李< / ul > < / >
        • com4为: result = (str2 == str3)
          • 比较stringstring,因此执行字符串值检查
          • str2和str3都是“String”,所以结果为真
          • 李< / ul > < / >
          • com5: result = (str2 == str4)
            • 比较stringstring,因此执行字符串值检查
            • str2和str4都是“String”,所以结果为真
            • 李< / ul > < / >
            • com6: result = (str3 == str4)
              • 比较stringstring,因此执行字符串值检查
              • str3和str4都是“String”,所以结果为真
              • 李< / ul > < / >
              • com7: result = (obj == obj2) -比较objectobject,因此执行引用是否相等检查 - obj和obj2指向不同的引用,因此结果为false

在==和String之间有一个细微但非常重要的区别。=方法:

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

你可以看到==操作符将返回给两个明显相等的字符串。为什么?因为泛型方法中使用的==运算符被解析为System定义的op_equal方法。对象(该方法在编译时拥有的T的唯一保证),这意味着它是引用相等而不是值相等。

当有两个值类型为System时。String,则==具有值相等语义,因为编译器将==解析为System.String。op_equal代替System.Object.op_equal。

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

如果其中一个值为空,为了避免nullreferenceexception,我总是使用静态 String。=方法:

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