C# 为什么要在 == 上使用 String.Equals?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1659097/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 19:46:14  来源:igfitidea点击:

Why would you use String.Equals over ==?

c#stringequals

提问by JamesBrownIsDead

I recently was introduced to a large codebase and noticed all string comparisons are done using String.Equals()instead of ==

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

What's the reason for this, do you think?

这是什么原因,你觉得呢?

回答by Jorge Israel Pe?a

There's a writeup on this articlewhich you might find to be interesting, with some quotes from Jon Skeet. It seems like the use is pretty much the same.

有一个书面记录这篇文章,你可能会发现很有趣,从乔恩斯基特一些报价。好像用法差不多。

Jon Skeet states that the performance of instance Equals "is slightly better when the strings are short—as the strings increase in length, that difference becomes completely insignificant."

Jon Skeet 指出,实例 Equals 的性能“当字符串较短时会稍微好一些——随着字符串长度的增加,这种差异变得完全无关紧要。”

回答by Matthew Scharley

It's entirely likely that a large portion of the developer base comes from a Java background where using ==to compare strings is wrong and doesn't work.

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

In C# there's no (practical) difference (for strings) as long as they are typed as string.

在 C# 中,只要将它们输入为字符串,就没有(实际的)区别(对于字符串)。

If they are typed as objector Tthen see other answers here that talk about generic methods or operator overloading as there you definitely want to use the Equals method.

如果它们被输入为objectT然后在这里看到其他讨论泛型方法或运算符重载的答案,因为在那里你肯定想使用 Equals 方法。

回答by Michael Petrotta

String.Equalsdoes offer overloads to handle casing and culture-aware comparison. If your code doesn't make use of these, the devs may just be used to Java, where (as Matthew says), you must use the .Equals method to do content comparisons.

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

回答by thezar

Both methods do the same functionally- they compare values.
As is written on MSDN:

这两种方法在功能上都是一样的——它们比较
正如 MSDN 上所写:

But if one of your string instances is null, these methods are working differently:

但是,如果您的字符串实例之一为空,则这些方法的工作方式不同:

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

回答by Andrew

I've just been banging my head against a wall trying to solve a bug because I read this page and concluded there was no meaningful difference when in practice there is so I'll post this link here in case anyone else finds they get different results out of == and equals.

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

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

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

回答by Matthijs Wessels

I want to add that there is another difference. It is related to what Andrew posts.

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

It is also related to a VERY annoying to find bug in our software. See the following simplified example (I also omitted the null check).

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

public const int SPECIAL_NUMBER = 213;

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

This will compile and always return false. While the following will give a compile error:

这将编译并始终返回false。虽然以下将给出编译错误:

public const int SPECIAL_NUMBER = 213;

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

We have had to solve a similar problem where someone compared enums of different type using Equals. You are going to read over this MANY times before realising it is the cause of the bug. Especially if the definition of SPECIAL_NUMBERis not near the problem area.

我们不得不解决一个类似的问题,即有人使用Equals. 在意识到它是错误的原因之前,您将多次阅读此内容。特别是如果 的定义SPECIAL_NUMBER不在问题区域附近。

This is why I am really against the use of Equals in situations where is it not necessary. You lose a little bit of type-safety.

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

回答by vikas

There is practical difference between string.Equalsand ==

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

Adding Watch

添加监视

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

Now look at {1#}and {5#}

现在看看{1#}{5#}

obj, str2, str4and obj2references are same.

obj, str2,str4obj2参考文献相同。

objand obj2are object typeand others are string type

obj并且obj2object type和其他人string type

Conclusion:

结论

  1. com1: result = (obj == str2);// true
    • compares objectand stringso performs a reference equality check
    • obj and str2 point to the same reference so the result is true
  2. com2: result = (obj == str3);// false
    • compares objectand stringso performs a reference equality check
    • obj and str3 point to the different references so the result is false
  3. com3: result = (obj == str4);// true
    • compares objectand stringso performs a reference equality check
    • obj and str4 point to the same reference so the result is true
  4. com4: result = (str2 == str3);// true
    • compares stringand stringso performs a string value check
    • str2 and str3 are both "String" so the result is true
  5. com5: result = (str2 == str4);// true
    • compares stringand stringso performs a string value check
    • str2 and str4 are both "String" so the result is true
  6. com6: result = (str3 == str4);// true
    • compares stringand stringso performs a string value check
    • str3 and str4 are both "String" so the result is true
  7. com7: result = (obj == obj2);// false ?- compares objectand objectso performs a reference equality check ? ? ?- obj and obj2 point to the different references so the result is false
  1. com1: 结果 = (obj == str2);// 真
    • 比较objectstring因此执行引用相等性检查
    • obj 和 str2 指向同一个引用,所以结果为真
  2. com2: 结果 = (obj == str3);// 假
    • 比较objectstring因此执行引用相等性检查
    • obj 和 str3 指向不同的引用,因此结果为 false
  3. com3: 结果 = (obj == str4);// 真
    • 比较objectstring因此执行引用相等性检查
    • obj 和 str4 指向相同的引用,所以结果为真
  4. com4: 结果 = (str2 == str3);// 真
    • 比较stringstring执行字符串值检查
    • str2 和 str3 都是“字符串”,所以结果为真
  5. com5: 结果 = (str2 == str4);// 真
    • 比较stringstring执行字符串值检查
    • str2 和 str4 都是“字符串”,所以结果为真
  6. com6: 结果 = (str3 == str4);// 真
    • 比较stringstring执行字符串值检查
    • str3 和 str4 都是“字符串”,所以结果为真
  7. com7: result = (obj == obj2);// false ?- 比较objectobject执行引用相等性检查 ? ? ?- obj 和 obj2 指向不同的引用,所以结果为假

回答by Andrew Arnott

There is one subtle but very important differencebetween == and the String.Equals methods:

== 和 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);
        }
    }
}

Produces this output:

产生这个输出:

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

You can see that the == operator is returning falseto two obviously equal strings. Why? Because the == operator in use in the generic method is resolved to be the op_equal method as defined by System.Object (the only guarantee of T the method has at compile time), which means that it's reference equality instead of value equality.

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

When you have two values typed as System.String explicitly, then == has a value-equality semantic because the compiler resolves the == to System.String.op_equal instead of System.Object.op_equal.

当您有两个显式类型为 System.String 的值时,== 具有值相等语义,因为编译器将 == 解析为 System.String.op_equal 而不是 System.Object.op_equal。

So to play it safe, I almost always use String.Equals instead to that I always get the value equality semantics I want.

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

And to avoid NullReferenceExceptions if one of the values is null, I always use the staticString.Equals method:

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

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