Are string.Equals() and == operator really same? [duplicate]
Solution 1:
Two differences:
-
Equals
is polymorphic (i.e. it can be overridden, and the implementation used will depend on the execution-time type of the target object), whereas the implementation of==
used is determined based on the compile-time types of the objects:// Avoid getting confused by interning object x = new StringBuilder("hello").ToString(); object y = new StringBuilder("hello").ToString(); if (x.Equals(y)) // Yes // The compiler doesn't know to call ==(string, string) so it generates // a reference comparision instead if (x == y) // No string xs = (string) x; string ys = (string) y; // Now *this* will call ==(string, string), comparing values appropriately if (xs == ys) // Yes
-
Equals
will throw an exception if you call it on null, == won'tstring x = null; string y = null; if (x.Equals(y)) // NullReferenceException if (x == y) // Yes
Note that you can avoid the latter being a problem using object.Equals
:
if (object.Equals(x, y)) // Fine even if x or y is null
Solution 2:
The apparent contradictions that appear in the question are caused because in one case the Equals
function is called on a string
object, and in the other case the ==
operator is called on the System.Object
type. string
and object
implement equality differently from each other (value vs. reference respectively).
Beyond this fact, any type can define ==
and Equals
differently, so in general they are not interchangeable.
Here’s an example using double
(from Joseph Albahari’s note to §7.9.2 of the C# language specification):
double x = double.NaN;
Console.WriteLine (x == x); // False
Console.WriteLine (x != x); // True
Console.WriteLine (x.Equals(x)); // True
He goes on to say that the double.Equals(double)
method was designed to work correctly with lists and dictionaries. The ==
operator, on the other hand, was designed to follow the IEEE 754 standard for floating point types.
In the specific case of determining string equality, the industry preference is to use neither ==
nor string.Equals(string)
most of the time. These methods determine whether two string are the same character-for-character, which is rarely the correct behavior. It is better to use string.Equals(string, StringComparison)
, which allows you to specify a particular type of comparison. By using the correct comparison, you can avoid a lot of potential (very hard to diagnose) bugs.
Here’s one example:
string one = "Caf\u00e9"; // U+00E9 LATIN SMALL LETTER E WITH ACUTE
string two = "Cafe\u0301"; // U+0301 COMBINING ACUTE ACCENT
Console.WriteLine(one == two); // False
Console.WriteLine(one.Equals(two)); // False
Console.WriteLine(one.Equals(two, StringComparison.InvariantCulture)); // True
Both strings in this example look the same ("Café"), so this could be very tough to debug if using a naïve (ordinal) equality.
Solution 3:
C# has two "equals" concepts: Equals
and ReferenceEquals
. For most classes you will encounter, the ==
operator uses one or the other (or both), and generally only tests for ReferenceEquals
when handling reference types (but the string
Class is an instance where C# already knows how to test for value equality).
-
Equals
compares values. (Even though two separateint
variables don't exist in the same spot in memory, they can still contain the same value.) -
ReferenceEquals
compares the reference and returns whether the operands point to the same object in memory.
Example Code:
var s1 = new StringBuilder("str");
var s2 = new StringBuilder("str");
StringBuilder sNull = null;
s1.Equals(s2); // True
object.ReferenceEquals(s1, s2); // False
s1 == s2 // True - it calls Equals within operator overload
s1 == sNull // False
object.ReferenceEquals(s1, sNull); // False
s1.Equals(sNull); // Nono! Explode (Exception)
Solution 4:
The Header
property of the TreeViewItem
is statically typed to be of type object
.
Therefore the ==
yields false
. You can reproduce this with the following simple snippet:
object s1 = "Hallo";
// don't use a string literal to avoid interning
string s2 = new string(new char[] { 'H', 'a', 'l', 'l', 'o' });
bool equals = s1 == s2; // equals is false
equals = string.Equals(s1, s2); // equals is true