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?
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?
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.
.Equals
does offer more options but str1.Equals(str2)
is the same as str1 == str2
as far as what you get as a result. I do believe they use different methods for determining the equality as Jon Skeets quote that Blaenk brings up would indicate, but they give the same values. –
Claque this
is null or not) –
Claque .Equals
is a null reference exception if you try to call it on an object that is null, ie. string str1 = null; str1.Equals()
. This isn't an issue with Equals()
, that happens with any function and should be self-evident. The actual functionality of the two comparisons is always exactly the same given the same inputs. –
Claque a == b
instead of a.Equals(b)
. Am I off on this? –
Paleobiology string.Equals and ==
–
Nachison string
! (object)"a" == (object)"a"
will use object
s equality operator which will use reference equality and return false in a non-trivial example (in this exact case the compiler will use the same memory for both equivalent compile-time constants). See vikas's answer below. –
Claque string.==
operator does the same thing internally as string.Equals
? –
Leid Equals()
. Don't rely on NullPointerException's to catch your nulls - you should be checking if you suspect a null is possible. –
Claque .Equals()
is null. This is why you should/could use string.Equals()
instead of myString.Equals()
. –
Lumpy 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
object
and string
so performs a reference equality checkobject
and string
so performs a reference equality checkobject
and string
so performs a reference equality checkstring
and string
so performs a string value checkstring
and string
so performs a string value checkstring
and string
so performs a string value checkobject
and object
so performs a reference equality check
- obj and obj2 point to the different references so the result is falsestring.Equals(object, object)
is object.Equals(object, object)
which calls Equals
on the first argument, unlike ==
operator, which, unless overloaded, calls ReferenceEquals
. –
Telescope "String"
and typeof(string).Name
are different references is that the former, as a compile-time constant, is interned, whereas the latter, as a run-time value, is not. –
Cordwain string
for Equals
but CapCase String
for ReferenceEquals
? –
Incommunicable string
instead String
as string
is just alias of System.String
–
Nachison object
to a string
, I'm not sure it's a practical comparison, since if you already know the value is a string in order to consider string.Equals()
an alternative, you should be using a variable of the appropriate type. You now also have the option of using obj is "String"
, but not obj is obj2
, however if you can't narrow down the type from object
, there's really no point in testing for equality unless you want to use serialization or maybe exhaustive type tests. –
Mieshamiett 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));
Object
. If var myItem=GetItem()
reads an Object
from the database, the expressions "Hi".Equals(myItem)
, myItem.Equals("Hi")
, and Object.Equals("Hi", myItem)
will all return True
if the returned object is a string
with two characters "Hi", but myItem == "Hi"
or "Hi" == myItem
will test reference equality. The "Option Strict On" dialect of VB.NET is better in that regard. Its "=" operator tests either tests value equality or won't compile; for a reference-equality check, one uses the "Is" operator. –
Allochthonous "a" == "ab".Substring(0, 1)
on csharppad.com I get back true
. Same if I use String
objects. Explanation? –
Soredium System.String
overload of the ==
operator. The case you have to be cautious of is when the compiler doesn't know what type it is, such as when the compared expressions are typed as T
or System.Object
. –
Valentinvalentina .Substring()
causes different behavior? As it returns a string
, not a string
wrapped in an object
, why does it not have the same behavior as the first check? To me, it seems like both should have the exact same output. It's guaranteed to be a string comparison in the second example, just as it is in the first. –
Anaesthesiology ==
operator used in the generic method is an object ==
operator rather than a string==
operator. The reason .Substring(1)
produces a different result is that the method creates a new string object rather than possibly reusing another one that already has the same value. Thus as the two strings with equivalent values but different objects are seen as different by the generic method. –
Valentinvalentina 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.
==
does not explicitly tell the reader what is expected to happen with regard to case-sensitivity and culture. –
Lumpy Both methods do the same functionally - they compare values.
As is written on MSDN:
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)==
- 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");
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."
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.
Equals
and ReferenceEquals
had always used them) that would disallow implicit conversions, upcasts, boxing conversions, or combinations of the above. I also wish some operator other than ==
had been used for reference equality. Having Equals
and ==
define equivalence relations with all argument types where they compile would be more helpful than having them compile in cases that do not yield equivalence relations. –
Allochthonous 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
Object == Object
resolves to System.Object.ReferenceEquals
and a
and b
are two different objects in memory. The remainder compare the values of the string objects. Even the last comparison, which seems to call .Equals
for the Object
type object, as it is implemented as a virtual
method, it defaults to calling String.Equals
. –
Hurwitz © 2022 - 2024 — McMap. All rights reserved.
==
can be used to compare string contents in C#. – DamondamourEquals
may be preferred since the appearance of the null-propagation operator, because you may returnfalse
also in case of both stringnull
, in a very concise way; like this:if(firstString?.Equals(secondString) ?? false)
– Slim