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:
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.
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.
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.
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