可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
This question already has an answer here:
-
C# difference between == and Equals()
16 answers
I recently was introduced to a large codebase and noticed all string comparisons are done using String.Equals()
instead of ==
What\'s the reason for this, do you think?
回答1:
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.
In C# there\'s no (practical) difference (for strings) as long as they are typed as string.
If they are typed as object
or T
then see other answers here that talk about generic methods or operator overloading as there you definitely want to use the Equals method.
回答2:
There is practical difference between string.Equals
and ==
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#}
obj
, str2
, str4
and obj2
references are same.
obj
and obj2
are object type
and others are string type
Conclusion:
- com1: result = (obj == str2);// true
- compares
object
and string
so performs a reference equality check
- obj and str2 point to the same reference so the result is true
- com2: result = (obj == str3);// false
- compares
object
and string
so performs a reference equality check
- obj and str3 point to the different references so the result is false
- com3: result = (obj == str4);// true
- compares
object
and string
so performs a reference equality check
- obj and str4 point to the same reference so the result is true
- com4: result = (str2 == str3);// true
- compares
string
and string
so performs a string value check
- str2 and str3 are both \"String\" so the result is true
- com5: result = (str2 == str4);// true
- compares
string
and string
so performs a string value check
- str2 and str4 are both \"String\" so the result is true
- com6: result = (str3 == str4);// true
- compares
string
and string
so performs a string value check
- str3 and str4 are both \"String\" so the result is true
- com7: result = (obj == obj2);// false
- compares
object
and object
so performs a reference equality check
- obj and obj2 point to the different references so the result is false
回答3:
There is one subtle but very important difference between == and the String.Equals methods:
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
You can see that the == operator is returning false to 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.
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.
So to play it safe, I almost always use String.Equals instead to that I always get the value equality semantics I want.
And to avoid NullReferenceExceptions if one of the values is null, I always use the static String.Equals method:
bool true = String.Equals(\"a\", \"ba\".Substring(1));
回答4:
String.Equals
does 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.
回答5:
Both methods do the same functionality - to compare values.
As it is written in MSDN:
- About String.Equals method - Determines whether this instance and
another specified String object have the same value. (http://msdn.microsoft.com/en-us/library/858x0yyx.aspx)
- About \'==\' - Although string is a reference type, the equality operators (== and
!=) are defined to compare the values of string objects, not
references. This makes testing for string equality more intuitive. (http://msdn.microsoft.com/en-en/library/362314fe.aspx)
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\");
回答6:
There\'s a writeup on this article which 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.\"
回答7:
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:
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_NUMBER
is not near the problem area.
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.
回答8:
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?
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