Reputation: 5817
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
Upvotes: 6
Views: 710
Reputation: 430
The ==
operator compares references (the memory addresses) while .Equals compares the actual object values. In the case of string, you get lucky and two identical strings can refer to the same address frequently. One of the joys of managed languages.
Upvotes: 0
Reputation: 4657
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?
Upvotes: 1
Reputation: 86506
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.
Upvotes: 1
Reputation: 460028
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
Upvotes: 1
Reputation: 1427
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.
Upvotes: 1
Reputation: 498904
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.
Upvotes: 10
Reputation: 62248
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.
Upvotes: 2
Reputation: 1968
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.
Upvotes: 9
Reputation: 25799
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.
Upvotes: 3