This question already has answers here:
C# difference between == and Equals()
(20 answers)
Closed 9 years ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
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.
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
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));
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.
Both methods do the same functionally - they compare values.
As is written on 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");
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.
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
Related
I have a condition in a silverlight application that compares 2 strings, for some reason when I use == it returns false while .Equals() returns true.
Here is the code:
if (((ListBoxItem)lstBaseMenu.SelectedItem).Content.Equals("Energy Attack"))
{
// Execute code
}
if (((ListBoxItem)lstBaseMenu.SelectedItem).Content == "Energy Attack")
{
// Execute code
}
Any reason as to why this is happening?
When == is used on an expression of type object, it'll resolve to System.Object.ReferenceEquals.
Equals is just a virtual method and behaves as such, so the overridden version will be used (which, for string type compares the contents).
When comparing an object reference to a string (even if the object reference refers to a string), the special behavior of the == operator specific to the string class is ignored.
Normally (when not dealing with strings, that is), Equals compares values, while == compares object references.
If two objects you are comparing are referring to the same exact instance of an object, then both will return true, but if one has the same content and came from a different source (is a separate instance with the same data), only Equals will return true. However, as noted in the comments, string is a special case because it overrides the == operator so that when dealing purely with string references (and not object references), only the values are compared even if they are separate instances. The following code illustrates the subtle differences in behaviors:
string s1 = "test";
string s2 = "test";
string s3 = "test1".Substring(0, 4);
object s4 = s3; // Notice: set to object variable!
Console.WriteLine($"{object.ReferenceEquals(s1, s2)} {s1 == s2} {s1.Equals(s2)}");
Console.WriteLine($"{object.ReferenceEquals(s1, s3)} {s1 == s3} {s1.Equals(s3)}");
Console.WriteLine($"{object.ReferenceEquals(s1, s4)} {s1 == s4} {s1.Equals(s4)}");
The output is:
True True True // s1, s2
False True True // s1, s3
False False True // s1, s4
Summary:
Variables
.ReferenceEquals
==
.Equals
s1, s2
True
True
True
s1, s3
False
True
True
s1, s4
False
False
True
== and .Equals are both dependent upon the behavior defined in the actual type and the actual type at the call site. Both are just methods / operators which can be overridden on any type and given any behavior the author so desires. In my experience, I find it's common for people to implement .Equals on an object but neglect to implement operator ==. This means that .Equals will actually measure the equality of the values while == will measure whether or not they are the same reference.
When I'm working with a new type whose definition is in flux or writing generic algorithms, I find the best practice is the following
If I want to compare references in C#, I use Object.ReferenceEquals directly (not needed in the generic case)
If I want to compare values I use EqualityComparer<T>.Default
In some cases when I feel the usage of == is ambiguous I will explicitly use Object.Reference equals in the code to remove the ambiguity.
Eric Lippert recently did a blog post on the subject of why there are 2 methods of equality in the CLR. It's worth the read
http://blogs.msdn.com/ericlippert/archive/2009/04/09/double-your-dispatch-double-your-fun.aspx
== Operator
If operands are Value Types and their values are equal, it returns true else false.
If operands are Reference Types with exception of string and both refer to the same instance (same object), it returns true else false.
If operands are string type and their values are equal, it returns true else false.
.Equals
If operands are Reference Types, it performs Reference Equality that is if both refer to the same instance (same object), it returns true else false.
If Operands are Value Types then unlike == operator it checks for their type first and if their types are same it performs == operator else it returns false.
As far as I understand it the answer is simple:
== compares object references.
.Equals compares object content.
String datatypes always act like content comparison.
I hope I'm correct and that it answered your question.
Firstly, there is a difference. For numbers
> 2 == 2.0
True
> 2.Equals(2.0)
False
And for strings
> string x = null;
> x == null
True
> x.Equals(null)
NullReferenceException
In both cases, == behaves more usefully than .Equals
I would add that if you cast your object to a string then it will work correctly. This is why the compiler will give you a warning saying:
Possible unintended reference comparison; to get a value comparison,
cast the left hand side to type 'string'
Because the static version of the .Equal method was not mentioned so far, I would like to add this here to summarize and to compare the 3 variations.
MyString.Equals("Somestring")) //Method 1
MyString == "Somestring" //Method 2
String.Equals("Somestring", MyString); //Method 3 (static String.Equals method) - better
where MyString is a variable that comes from somewhere else in the code.
Background info and to summerize:
In Java using == to compare strings should not be used. I mention this in case you need to use both languages and also
to let you know that using == can also be replaced with something better in C#.
In C# there's no practical difference for comparing strings using Method 1 or Method 2 as long as both are of type string. However, if one is null, one is of another type (like an integer), or one represents an object that has a different reference, then, as the initial question shows, you may experience that comparing the content for equality may not return what you expect.
Suggested solution:
Because using == is not exactly the same as using .Equals when comparing things, you can use the static String.Equals method instead. This way, if the two sides are not the same type you will still compare the content and if one is null, you will avoid the exception.
bool areEqual = String.Equals("Somestring", MyString);
It is a little more to write, but in my opinion, safer to use.
Here is some info copied from Microsoft:
public static bool Equals (string a, string b);
Parameters
a String
The first string to compare, or null.
b String
The second string to compare, or null.
Returns Boolean
true if the value of a is the same as the value of b; otherwise, false. If both a and b are null, the method returns true.
Just as an addition to the already good answers: This behaviour is NOT limited to Strings or comparing different numbertypes. Even if both elements are of type object of the same underlying type. "==" won't work.
The following screenshot shows the results of comparing two object {int} - values
I am a bit confused here. If the runtime type of Content is of type string, then both == and Equals should return true. However, since this does not appear to be the case, then runtime type of Content is not string and calling Equals on it is doing a referential equality and this explains why Equals("Energy Attack") fails. However, in the second case, the decision as to which overloaded == static operator should be called is made at compile time and this decision appears to be ==(string,string). this suggests to me that Content provides an implicit conversion to string.
There is another dimension to an earlier answer by #BlueMonkMN. The additional dimension is that the answer to the #Drahcir's title question as it is stated also depends on how we arrived at the string value. To illustrate:
string s1 = "test";
string s2 = "test";
string s3 = "test1".Substring(0, 4);
object s4 = s3;
string s5 = "te" + "st";
object s6 = s5;
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s2), s1 == s2, s1.Equals(s2));
Console.WriteLine("\n Case1 - A method changes the value:");
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s3), s1 == s3, s1.Equals(s3));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s4), s1 == s4, s1.Equals(s4));
Console.WriteLine("\n Case2 - Having only literals allows to arrive at a literal:");
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s5), s1 == s5, s1.Equals(s5));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s6), s1 == s6, s1.Equals(s6));
The output is:
True True True
Case1 - A method changes the value:
False True True
False False True
Case2 - Having only literals allows to arrive at a literal:
True True True
True True True
Adding one more point to the answer.
.EqualsTo() method gives you provision to compare against culture and case sensitive.
Really great answers and examples!
I would just like to add the fundamental difference between the two,
Operators such as == are not polymorphic, while Equals is
With that concept in mind, if you work out any example (by looking at left hand and right hand reference type, and checking/knowing if the type actually has == operator overloaded and Equals being overriden) you are certain to get the right answer.
This is due to value equality (equal method) and referential equality(== operator), as the equal method checks the values while the same == is checked the reference.
== operator overriding code available inside the string class on https://referencesource.microsoft.com/
so now it's easier to understand, the equal method also has 2 implementations one from the string class itself and one from the object class. its impact on performance as well I also run some basic code and try to understand the benchmarks.
I am sharing the results below Please correct or advise if I am wrong somewhere. there are 3 cases and I have run the same code for all the cases and this is the result.
case 1: here I am using string. equal method for comparing 2 strings and both the string have the same values. string.equals(a,b)
1st run:5608195 ticks
2nd run:5529387 ticks
3rd run:5622569 ticks
total ticks: 16760151
case 2: here I am using string. equal() method(overloaded one) for comparing 2 strings and both the string have the same values.
a.equals(b)
1st run: 6738583 ticks
2nd run: 6452927 ticks
3rd run: 7168897 ticks
total ticks=20360407
case 3: here I am using the == operator for comparing 2 strings and both the string have the same values.
a==b
1st run: 6652151 ticks
2nd run: 7514300 ticks
3rd run: 7634606 ticks
total ticks=21801057
class Program
{
private static int count;
static string a = "abcdef";
static string b = "abcdef";
static void Main(string[] args)
{
for (int j = 1; j <= 3; j++)
{
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 1; i <= 1000; i++)
{
checkString();
}
sw.Stop();
Console.WriteLine(sw.ElapsedTicks);
}
Console.ReadLine();
}
public static void checkString()
{
for (int i = 1; i <= 100000; i++)
{
if (a==b)
count++;
}
}
}
The == token in C# is used for two different equality-check operators. When the compiler encounters that token, it will check whether either of the types being compared has implemented an equality-operator overload for either the specific combination types being compared(*), or for a combination of types to which both types can be converted. If the compiler finds such an overload it will use it. Otherwise, if the two types are both reference types and they are not unrelated classes (either may be an interface, or they may be related classes), the compiler will regard == as a reference-comparison operator. If neither condition applies, compilation will fail.
Note that some other languages use separate tokens for the two equality-check operators. In VB.NET, for example, the = token is used within expressions solely for the overloadable equality-check operator, and Is is used as a reference-test or null-test operator. An to use = on a type which does not override the equality-check operator will fail, as will attempting to use Is for any purpose other than testing reference equality or nullity.
(*)Types generally only overload equality for comparison with themselves, but it may be useful for types to overload the equality operator for comparison with other particular types; for example, int could have (and IMHO should have but didn't) defined an equality operators for comparison with float, so that 16777217 would not report itself equal to 16777216f. As it is, since no such operator is defined, C# will promote the int to float, rounding it to 16777216f before the equality-check operator sees it; that operator then sees two equal floating-point numbers and reports them as equal, unaware of the rounding that took place.
Note that there are two different types of equality in C#
1- Value Equality (For value types like int, DateTime and struct)
2- Reference Equality (For objects)
There are two basic standard protocols for implement equality checks.
1- The == and != operators.
2- The virtual Equals method.
The == and != are statically resolve, which means C# will make a compile-time decision as to which type will perform the comparison.
For instance the value-type
int x = 50;
int y = 50;
Console.WriteLine (x == y); // True
but for reference type
object x = 50;
object y = 50;
Console.WriteLine (x == y); // False
The Equals() originally resoled at runtime according to operand actual type.
For instance, in the following example, at runtime, it will be decided that the Equals() will apply on int values, the result is true.
object x = 5;
object y = 5;
Console.WriteLine (x.Equals (y)); // True
However, for a reference type, it will use a reference equality check.
MyObject x = new MyObject();
MyObject y = x;
Console.WriteLine (x.Equals (y)); // True
Note that Equals() uses structural comparison for struct, which means it calls Equals on each field of a struct.
Whether Equals() and == are the same depends on the implementation. Because C# allows users to set different behaviors for Equals() and == respectively.
class CompareTest
{
public readonly int val;
public CompareTest(int val)
{
this.val = val;
}
public override bool Equals(object obj)
{
return obj is CompareTest test && this.val == test.val;
}
public override int GetHashCode()
{
return val;
}
public static bool operator == (CompareTest a, object b)
{
return Equals(a, b);
}
public static bool operator != (CompareTest a, object b)
{
return !(a == b);
}
}
In this example, I made Equals() and == have the same behavior. But what if I make them different? For example:
public static bool operator == (CompareTest a, object b)
{
return false;
}
Equals() works normally but == will never works.
Furthermore, although I made them have the same behavior, but there is still one difference: which == function will be called depends on the left value:
Compare Test a = new CompareTest(1);
object b = new CompareTest(1);
CompareTest c = new CompareTest(1);
Debug.Log("AB " + (a == b)); // true
Debug.Log("BA " + (b == a)); // false! because it calls object's == function
Debug.Log("AC " + (a == c)); // true
Debug.Log("CA " + (c == a)); // true
When we create any object there are two parts to the object one is the content and the other is reference to that content.
== compares both content and reference;
equals() compares only content
http://www.codeproject.com/Articles/584128/What-is-the-difference-between-equalsequals-and-Eq
==
The == operator can be used to compare two variables of any kind, and it simply compares the bits.
int a = 3;
byte b = 3;
if (a == b) { // true }
Note : there are more zeroes on the left side of the int but we don't care about that here.
int a (00000011) == byte b (00000011)
Remember == operator cares only about the pattern of the bits in the variable.
Use == If two references (primitives) refers to the same object on the heap.
Rules are same whether the variable is a reference or primitive.
Foo a = new Foo();
Foo b = new Foo();
Foo c = a;
if (a == b) { // false }
if (a == c) { // true }
if (b == c) { // false }
a == c is true
a == b is false
the bit pattern are the same for a and c, so they are equal using ==.
Equal():
Use the equals() method to see if two different objects are equal.
Such as two different String objects that both represent the characters in "Jane"
The only difference between Equal and == is on object type comparison. in other cases, such as reference types and value types, they are almost the same(either both are bit-wise equality or both are reference equality).
object:
Equals: bit-wise equality
==: reference equality
string: (equals and == are the same for string, but if one of string changed to object, then comparison result will be different)
Equals: bit-wise equality
== : bit-wise equality
See here for more explanation.
Why we have different output for below cases:
object obj = "Int32";
string str1 = "Int32";
string str2 = typeof(int).Name;
Console.WriteLine(obj == str1); // true
Console.WriteLine(str1 == str2); // true
Console.WriteLine(obj == str2); // false !?
The answer to this is quite simple:
When you compare an object with a string, a reference comparison is used, which will only be true if both objects have the same reference.
When you compare strings a string comparison is used, which will be true if the string contents are the same regardless of whether they are the same reference.
In your third comparison you are using an object comparison where you are comparing two strings with identical contents but with different references, so it will return false.
The added complication is that the first two strings have the same reference because they are compile-time constants and have been interned by the compiler so that they refer to the same string in memory.
I've annotated your original code with this explanation:
object obj = "Int32"; // As a compile-time constant string, this will be interned.
string str1 = "Int32"; // This is also interned, so has the same reference as obj
string str2 = typeof(int).Name; // Same contents as str1, but a different reference
// (created at runtime, so it wasn't interned)
Console.WriteLine(obj == str1); // Reference comparison: true because the references are the same
Console.WriteLine(str1 == str2); // String comparison: true because the string contents are the same.
Console.WriteLine(obj == str2); // Reference comparison: false because the references different.
Also:
If you are using Resharper it actually warns you for the first and last comparison, saying: "Possible unintended reference comparison".
You can get the same result by declaring str2 as follows:
string str2 = string.Concat("Int", "32");
The obj == str2 line used reference comparison. Whereas the obj == str1 line did not.
Why?
The string type in .NET is an implicit reference type. But it's not at the same time. It's one of those types that is technically a reference type, but it's been programmed to act like a value type, and is immutable, meaning it is not directly modified.
When you create a new string, a reference is allocated for it and that reference is what your string variable holds. You get to do all sorts of things with that string, but you can never change it. If you reassign the value it will merely create a new reference.
In this instance, the obj == str1 line used reference comparison, but the references actually matched. Because they were both hard-coded, the compiler, and .NET, can use the same reference for each. (As we said before, strings are immutable.) You should read the interning link Matthew posted for more information on that.
So, if the strings match, why did .NET create a different reference?
Consider the significant amount of objects you could create in memory. If, at any time, you created a new string and .NET went through all of the other strings to find one that matched, your programme would be phenomenally slow. You would barely get any real work done.
So, .NET optimizes this away. If you change your code a bit, you'll see what I mean.
object obj = "Int32";
string str1 = typeof(int).Name;
string str2 = typeof(int).Name;
Console.WriteLine(obj == str1); // false
Console.WriteLine(str1 == str2); // true
Console.WriteLine(obj == str2); // false !?
The str1 == str2 line still returns true, because it's actually comparing the strings, whereas the obj == str1 line is now false, because it's comparing the references of those as well.
This question already has answers here:
C# difference between == and Equals()
(20 answers)
Closed 9 years ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
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.
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
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));
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.
Both methods do the same functionally - they compare values.
As is written on 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");
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.
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
here is C# code.
class Program
{
static void Main(string[] args)
{
char [] arry = {'a', 'b', 'c'};
String str1 = 'a' + "bc";
String str2 = "bcd";
String str3 = new String(arry);
if (str1 == str2)
Console.WriteLine("str1 == str2");
if (str1 == str3)
Console.WriteLine("str1 == str3");
if (String.Equals(str1, str3))
Console.WriteLine("String.Equals(str1, str3)");
String str4 = GetStr();
if (str1 == str4)
Console.WriteLine("str1 == str4");
if (String.Equals(str1, str4))
Console.WriteLine("String.Equals(str1, str4)");
if (str3 == str4)
Console.WriteLine("str3 == str4");
if (String.Equals(str3, str4))
Console.WriteLine("String.Equals(str3, str4)");
}
public static String GetStr()
{
String str = "ab" + 'c';
return str;
}
}
And result is ..
str1 == str3
String.Equals(str1, str3)
str1 == str4
String.Equals(str1, str4)
str3 == str4
String.Equals(str3, str4)
Why all results say "Equal!" ??
As I knew, reference value are different each others.
So, results should have been "different!". but not.
Why?
It seems that there is no reason to use String.equal() !!
You are confusing string.Equals with object.ReferenceEquals.
string.Equals overrides object.Equals (which has the same semantics as ReferenceEquals) and works by comparing the values of the strings. This is the reason that object.Equals is virtual in the first place.
Equality for a string has been overridden to be based on its value.
The documentation for String.Equals states it checks the value, but that also happens to be what == also does due to the string implementation.
Default equality for reference types is based on the reference itself, but that can easily be overridden... so basically your assertion is flawed, as it doesn't take into account types that override default behaviour.
As Jon has stated, reference equality can be forced via the object.ReferenceEquals static method, but as Jason has stated, this may also fail if the strings have been interned.
According to ILSpy, String.Equals ends up using == at any rate:
public static bool Equals(string a, string b)
{
return a == b || (a != null && b != null && a.Length == b.Length && string.EqualsHelper(a, b));
}
== has been overloaded for String to evaluate equality as values, not as references. From MSDN:
Although string is a reference type, the equality operators (== and !=) are defined to compare the values of string objects, not references.
However, what you need to be aware of is that some of the strings will be evaluated at compile-time, and the compiler will intern them (that is, hold a single reference to a string with a given value). Therefore, these strings might be equal as references too (but that is not guaranteed to be the case).
String.Equals Method
Determines whether two String objects have the same value.
This means that your ouput is completely normal.
Each string literal does not necessarily result in a new string instance. When two or more string literals that are equivalent according to the string equality operator appear in the same assembly, these string literals refer to the same string instance. For instance, the output produced by
class Test
{
static void Main() {
object a = "hello";
object b = "hello";
System.Console.WriteLine(a == b);
}
}
is True because the two literals refer to the same string instance.
you can see this for completely:
http://msdn.microsoft.com/en-us/library/aa691090%28v=vs.71%29.aspx
For comparing string you should use:
var1string.CompareTo(var2string) == 0
This is the correct way to compare strings
So change :
if (str1 == str2)
with this:
if (str1.CompareTo(str2) == 0)
And the rest too.
I know there are a lot of ways to compare VALUE and REFERENCES in C#, but I'm still a bit confused about what type performs what when you try to compare either VALUE or REFERENCE.
String examples:
string str = "hello";
string str2 = "hello";
if (str == str2)
{
Console.WriteLine("Something");
} // Is this a comparison of value?
if (str.Equals(str2))
{
Console.WriteLine("Something");
} // Is this a comparison of value?
string.ReferenceEquals(str, str2); // Comparison of reference (True)
Console.WriteLine((object)str1 == (object)str2); // Comparison of reference (True)
Equals and == will compare by reference by default if they're not overriden / overloaded in a subclass. ReferenceEquals will always compare by reference.
Strings are a confusing data type to use for experimenting with this, because they overload == to implement value equality; also, since they're immutable, C# will generally reuse the same instance for the same literal string. In your code, str and str2 will be the same object.
#Inerdia is right with what he says but I'd like to point out the reason why the line string.ReferenceEquals(str, str2) returns true in your code example. Because you are defining both of the strings at compile time, the compiler can optimise the code so they can both point to the same instance of the string. Since strings are immutable the compiler knows it can do this even though String is a reference type. But If you change your code to dynamically generate one of the strings (as shown below) the compiler can't perform this optimisation. So in your code example if you change your code to:
string str = "hello";
string str2 = new StringBuilder().Append("he").Append("llo").ToString();
Then the string.ReferenceEquals(str, str2) line will now return false as this time the compiler cant know to re-use the same instance (reference of the string).
Equality and Comparision of ReferenceTypes and strings:
Reference types work like this:
System.Object a = new System.Object();
System.Object b = new System.Object();
a == b; //returns true
a.Equals(b); //returns false
b = a;
a == b; //returns true
a.Equals(b); //returns true
Since strings are Reference types they should do the same, shouldn't they? But they don't!
C# Documentation defines string equality like this:
Although string is a reference type, the equality operators (== and
!=) are defined to compare the values of string objects, not
references (7.9.7 String equality operators). This makes testing for
string equality more intuitive.
https://msdn.microsoft.com/en-us/library/362314fe%28v=vs.71%29.aspx
https://msdn.microsoft.com/en-us/library/aa664728%28v=vs.71%29.aspx
This has implications for you test code.
if (str == str2)
{
Console.WriteLine("Something");
} // This is comparision of value even though string is a referenceType
if (str.Equals(str2))
{
Console.WriteLine("Something");
} // This is comparison by value too, because Equals is overrided in String class.
Keep in mind you as a programmer (Or your tricky coworker) can override .Equals(), changing it's behaviour, what you see above is what should happen. It's not necessarily in line with your codebase-reality, when in doubt check out the definition by marking .Equals() and hitting F12.
Addendum for x.Equals
The behavior of object.Equals() should these rules:
List item
x.Equals(x) returns true.
x.Equals(y) returns the same value as y.Equals(x).
if (x.Equals(y) && y.Equals(z)) returns true, then x.Equals(z) returns true.
Successive invocations of x.Equals(y) return the same value as long as the objects referenced by x and y are not modified.
x.Equals(null) returns false.
https://msdn.microsoft.com/ru-ru/library/ms173147%28v=vs.80%29.aspx
Whenever you are in doubt you can call x.ReferenceEquals, it's defined as following:
Unlike the Object.Equals(Object) method and the equality operator, the
Object.ReferenceEquals(Object) method cannot be overridden. Because of
this, if you want to test two object references for equality and you
are unsure about the implementation of the Equals method, you can call
the method.
https://msdn.microsoft.com/de-de/library/system.object.referenceequals%28v=vs.110%29.aspx
Thus:
System.Object a = new System.Object();
System.Object b = a;
System.Object.ReferenceEquals(a, b); //returns true
In your example the compiler merges your strings in optimization thus:
string str = "hello";
string str2 = "hello";
string.ReferenceEquals(str, str2); // Comparison of reference (True)
This behaviour is only duo to compiler optimization in your example, if we randomize the code it will return false:
string str = "hello";
string str2 = "hello";
if(throwCoin)
{
str2 = "bye";
}
string.ReferenceEquals(str, str2); // Comparison of reference (False)
string.ReferenceEquals(str, str2);
It obviously compares references.
str.Equals(str2)
Tries to compare references at first. Then it tries to compare by value.
str == str2
Does the same as Equals.
A good way to compare strings is to use string.Compare. If you want to ignore case, there is a parameter in place for that too.
Excerpt from .net sources:
public bool Equals(string value)
{
if (this == null)
throw new NullReferenceException();
else if (value == null)
return false;
else if (object.ReferenceEquals((object) this, (object) value))
return true;
else
return string.EqualsHelper(this, value);
}
So in general it is comparision of references first and if they don't match, it compares values.