I have these statements and their' results are near them.
string a = "abc";
string b = "abc";
Console.Writeline(a == b); //true
object x = a;
object y = b;
Console.Writeline(x == y); // true
string c = new string(new char[] {'a','b','c'});
string d = new string(new char[] {'a','b','c'});
Console.Writeline(c == d); // true
object k = c;
object m = d;
Console.Writeline(k.Equals(m)) //true
Console.Writeline(k == m); // false
Why the last equality gives me false ?
The question is why ( x == y ) is true ( k == m ) is false
Difference between == and . Equals method in c# The Equality Operator ( ==) is the comparison operator and the Equals() method in C# is used to compare the content of a string. The Equals() method compares only content.
Answering to the point “There is no difference between equality comparison using “==” and “Equals()”, except when you are comparing “String” comparison. The common comparison Rule :-Whenever youare comparing variables they are either value types or reference types.
The most common way to compare objects in C# is to use the == operator. For predefined value types, the equality operator (==) returns true if the values of its operands are equal, false otherwise. For reference types other than string, == returns true if its two operands refer to the same object.
== is the equality operator it is used to determine if variable is equal to another variable. === is the operator for strict equality, this checks not only that what is in the bucket is the same, but that the type of variable is also the same, so for instance...
In the case of strings, the ==
operator is overloaded to test for value equality, when using object
reference equality is used.
Since c
and d
are strings, when you use Equals
in the k
and m
, the overloaded method is used.
And c == d
is true
for the reason state above - value equality is used on string
types as the operator is overloaded.
string a = "abc";
string b = "abc";
Console.Writeline(a == b); //true
String references are the same for the same string due to String Interning
object x = a;
object y = b;
Console.Writeline(x == y); // true
Because the references are the same, two objects created from the same reference are also the same.
string c = new string(new char[] {'a','b','c'});
string d = new string(new char[] {'a','b','c'});
Here you create two NEW arrays of characters, these references are different.
Console.Writeline(c == d); // true
Strings have overloaded == to compare by value.
object k = c;
object m = d;
Since the previous references are different, these objects are different.
Console.Writeline(k.Equals(m)) //true
.Equals
uses the overloaded String equals
method, which again compare by value
Console.Writeline(k == m); // false
Here we check to see if the two references are the same... they are not
The key is figuring out when an equality is comparing references or values.
Objects, unless otherwise overloaded, compare references.
Structs, unless otherwise overloaded, compare values.
Because they are two different object references. The built-in comparison for this is to compare whether they point to the same actual object or not.
Due to String Interning, a
and b
are both references to the same string object.
c==d
is true because the string equality operator is being used.
string c = new string(new char[] {'a','b','c'});
string d = new string(new char[] {'a','b','c'});
Console.WriteLine(c == d); // true
object k = c;
object m = d;
Console.WriteLine(k.Equals(m)); //true
Console.WriteLine(k == m); // false
Generates IL code, like this:
IL_0001: ldc.i4.3
IL_0002: newarr System.Char
IL_0007: dup
IL_0008: ldtoken <PrivateImplementationDetails>{61BB33F4-0CA5-4733-B259-764124AD1A79}.$$method0x6000002-1
IL_000D: call System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray
IL_0012: newobj System.String..ctor
IL_0017: stloc.0
IL_0018: ldc.i4.3
IL_0019: newarr System.Char
IL_001E: dup
IL_001F: ldtoken <PrivateImplementationDetails>{61BB33F4-0CA5-4733-B259-764124AD1A79}.$$method0x6000002-2
IL_0024: call System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray
IL_0029: newobj System.String..ctor
IL_002E: stloc.1
IL_002F: ldloc.0
IL_0030: ldloc.1
IL_0031: call System.String.op_Equality //STRING EQUALITY
IL_0036: call System.Console.WriteLine
IL_003B: nop
IL_003C: ldloc.0
IL_003D: stloc.2
IL_003E: ldloc.1
IL_003F: stloc.3
IL_0040: ldloc.2
IL_0041: ldloc.3
IL_0042: callvirt System.Object.Equals
IL_0047: call System.Console.WriteLine
IL_004C: nop
IL_004D: ldloc.2
IL_004E: ldloc.3
IL_004F: ceq //CEQ INSTRUCTION: **VALUES** EQUALITY !
IL_0051: call System.Console.WriteLine
As you can see the last instruction call CEQ instruction that makes comparison of values equality pushed on stack. The values pushed on stack are references of both boxed string, which are not equal.
As seen on C# FAQ on MSDN - the compiler cannot use the overloaded method and falls back to comparing the references.
The bigger question is why it succeeds in the first object comparison. My best guess is that succeeds because a and b are both given the same reference. For c and d, you are forcing different references.
String
has overloaded the equality operator so that you can use ==
for value comparison. Hence
a == b //true
.
When you're downcasting them to object, you're only comparing references.
String
looks into an internal string-pool if another string instance is already available, otherwise a new instance will be created and added to the pool. So actually a
, b
, x
and y
are even the same reference, that's why
x == y //true
.
With using the constructor of String
, you're forcing .NET to create a new instance even if another string with the same value(length and character sequence) exists. That's why
k == m //false
http://en.csharp-online.net/CSharp_String_Theory%E2%80%94String_intern_pool
When you say string1 == string2
, the comparison uses the string
type's overloaded ==
operator, which compares the strings' values.
When you say object1 == object2
, even though they're strings in this case, they won't qualify as strings for the purposes of finding an operator. So the comparison uses the default ==
operator, which compares the references for equality. Which means, if the two objects aren't the exact same object, it will return false.
Building on Bob2Chiv's, I tried the equivalent in VB (VS2010):
Dim a As String = "abc"
Dim b As String = "abc"
Console.WriteLine(a = b) ' True
Dim x As Object = a
Dim y As Object = b
Console.WriteLine(x = y) ' True
Dim c As String = New String(New Char() {"a"c, "b"c, "c"c})
Dim d As String = New String(New Char() {"a"c, "b"c, "c"c})
Console.WriteLine(c = d) ' True
Dim k As Object = c
Dim m As Object = d
Console.WriteLine(k.Equals(m)) ' True
Console.WriteLine(k = m) ' True (Yes, True!!)
Console.WriteLine(k Is m) ' False (Like in C#)
Console.WriteLine(a Is b) ' True (Like in C#)
(At least I think it's the equivalent - I welcome being corrected on this.)
Moral?: Be careful of ==
in C# - prefer .Equals()
when the comparison of values is what's desired?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With