I had a little fun today playing with ‘==’ vs. the Equals(…) method. I knew that somewhere in .NET 2.0 (I believe) there had been some improvements in String.Empty versus “”, but I didn’t quite realize that this affected all string literals.
In the code below you can see how value types and reference types may behave differently when using ‘==’ versus the Equals method.
My surprise came when I discovered that line 39 and 41 both return TRUE. Apparently the string literals in an assembly get put in a master list of string constants and then reused where the same string literal gets used. Nice!
The way to force the reference comparison of the string against object to actually be different is to delay the creation of the string until runtime, like in line 52.
1: static void Main(string[] args)
2: {
3:
4: // value types
5:
6: int x = 10;
7:
8: int y = 10;
9:
10: Console.WriteLine( x == y ); // compare by value -> return true
11:
12: Console.WriteLine( x.Equals( y ) ); // compare by value -> return true
13:
14: Console.WriteLine( object.ReferenceEquals( x, y ) ); // compare by reference -> return false
15:
16:
17: Console.ReadLine();
18:
19: // Reference types
20:
21: StringBuilder s1 = new StringBuilder( "yes" );
22:
23: StringBuilder s2 = new StringBuilder( "yes" );
24:
25: Console.WriteLine( s1 == s2 ); // compare by reference -> return false
26:
27: Console.WriteLine( s1.Equals( s2 ) ); // compare by value -> return true
28:
29: Console.WriteLine( object.ReferenceEquals( s1, s2 ) ); // compare by reference -> return false
30:
31: Console.ReadLine();
32:
33: // object and string
34:
35: object o1 = GetName();
36:
37: string o2 = "Mark";
38:
39: Console.WriteLine( o1 == o2 ); // compare by reference -> return true
40:
41: Console.WriteLine( o1.Equals( o2 ) ); // compare by value -> return true
42:
43: Console.WriteLine( object.ReferenceEquals( o1, o2 ) ); // compare by reference -> return true
44:
45: Console.ReadLine();
46:
47:
48: // object and string
49:
50: object ss1 = "Mark";
51:
52: string ss2 = "Markx".Substring( 0, 4 );
53:
54: Console.WriteLine( ss1 == ss2 ); // compare by reference -> return false
55:
56: Console.WriteLine( ss1.Equals( ss2 ) ); // compare by value -> return true
57:
58: Console.WriteLine( object.ReferenceEquals( ss1, ss2 ) ); // compare by reference -> return false
59:
60: Console.ReadLine();
61: }
62:
63: static object GetName()
64: {
65: return "Mark";
66: }