I am currently reading Jon Skeet's C# in Depth, 2nd Edition
. I'd like to quote listing 3.5:
static bool AreReferencesEqual<T>(T first, T second) where T : class
{
return first == second;
}
...
string name = "John";
string intro1 = "My name is " + name;
string intro2 = "My name is " + name;
Console.WriteLine(intro1 == intro2);
Console.WriteLine(AreReferencesEqual(intro1, intro2);
The author writes that the output should be True
for the first comparison and False
for the second one, because the overloaded operator is not used in the generic method. And he is, of course, right about the output.
Now let's change the code snippet a little bit:
static bool AreReferencesEqual<T>(T first, T second) where T : class
{
return first == second;
}
...
string intro1 = "John";
string intro2 = "John";
Console.WriteLine(intro1 == intro2);
Console.WriteLine(AreReferencesEqual(intro1, intro2);
Now both methods of comparing return True
. Let's tweak the code again, because this might have something to do with the fact that previously we compared variables that were created using an already existing string
.
static bool AreReferencesEqual<T>(T first, T second) where T : class
{
return first == second;
}
...
string name = "John"
string intro1 = name;
string intro2 = name;
Console.WriteLine(intro1 == intro2);
Console.WriteLine(AreReferencesEqual(intro1, intro2);
The output is True
in both situations.
Can anyone clarify what are the reasons for such behavior? Is there really such big of a difference between examples one and three?
Yes, there's a massive difference.
In example 1, intro1
and intro2
refer to different objects. In examples
2 and 3, intro1
and intro2
have the same value - they refer to the same object, so if you call Object.ReferenceEquals(intro1, intro2)
that will return true.
The reason for the behaviour is that the compiler has to work out what ==
means in AreReferencesEqual
at compile-time, without knowing the value of T
. It can't tell that you're going to call it with a type argument of string
, so it doesn't know about the overload of ==
. It's basically the same reason you couldn't call any other string-specific members in AreReferencesEqual
.
See more on this question at Stackoverflow