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
andstr2
will be the same object.Equality and Comparision of ReferenceTypes and strings:
Reference types work like this:
Since strings are Reference types they should do the same, shouldn't they? But they don't!
C# Documentation defines string equality like this:
This has implications for you test code.
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:
Whenever you are in doubt you can call x.ReferenceEquals, it's defined as following:
Thus:
In your example the compiler merges your strings in optimization thus:
This behaviour is only duo to compiler optimization in your example, if we randomize the code it will return false:
@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:
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).
It obviously compares references.
Tries to compare references at first. Then it tries to compare by value.
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:
So in general it is comparision of references first and if they don't match, it compares values.