Equality: == and Equals
Take two photocopies of one report. They are two different sheets, but the text on them is the same. Two links to a cloud document, on the other hand, lead to one and the same document. Whether two things are equal depends on the question: "is this the same thing?" or "do they hold the same thing?".
For strings, == answers the second question: it compares the text. For objects of a class, as you saw in the previous theme, == answers the first one. Every object also has the method Equals. What does it answer, and how do structs behave? Let's look at a class first:
Spot a = new Spot();
a.X = 1;
Spot b = new Spot();
b.X = 1;
Spot c = a;
Console.WriteLine(a == b); // False
Console.WriteLine(a == c); // True
Console.WriteLine(a.Equals(b)); // False
class Spot { public int X; }Let's go through the example line by line:
aandbare two different objects with the same fieldX = 1.a == bprintsFalse: for a class,==checks whether it is one object and does not compare the fields.Spot c = a;copies the reference, soa == cprintsTrue: both references lead to one object.Equalson a class compares references by default too, so the line printsFalse.
Two kinds of equality
The question "is this the same thing?" and the question "do they hold the same thing?" are two different kinds of equality:
- reference equality means two references lead to one object, like two links to one cloud document;
- value equality means the data match, like the text on two photocopies.
For classes, both == and Equals check reference equality by default. Two objects with the same fields are still two objects.
Here the picture with sheets is inexact. A person looking at two photocopies decides which question to ask. C# picks the question for you, by the kind of type: for a class, "is this one object?"; for Equals on a struct, "do the fields match?".
Equals on structs
A struct has no reference to compare: its value is stored right in the variable. That is why Equals on a struct compares all the fields by default:
Point p = new Point();
p.X = 1;
Point q = new Point();
q.X = 1;
Console.WriteLine(p.Equals(q)); // True
q.X = 2;
Console.WriteLine(p.Equals(q)); // False
struct Point { public int X; }While the fields of p and q match, Equals prints True. Once q.X changes, the points are different.
Two boxes of one number
Boxing creates an object, so two boxed numbers are two different boxes:
object first = 5;
object second = 5;
Console.WriteLine(first == second); // False
Console.WriteLine(first.Equals(second)); // TrueLet's look at the last two lines:
first == secondprintsFalse: for variables of typeobject, the==operator compares references, and there are two boxes.first.Equals(second)printsTrue:Equalson a boxedintcompares the numbers themselves.
Strings behave differently. string is a reference type, but both == and Equals compare its text: that is how the authors of the string type defined them. A class can decide for itself what == and Equals mean for it.
== or Equals
Interviewers like to ask: how does == differ from Equals? The answer depends on the kind of type:
- on a class, both compare references by default;
- on your own struct,
Equalscompares the fields, while==does not compile unless the struct declares it (the built-inint,doubleandboolalready have it); - on
string, both compare the text.
Common mistake
Someone tried to compare two structs with ==:
Point m = new Point();
Point n = new Point();
Console.WriteLine(m == n); // ✗error CS0019: Operator '==' cannot be applied to operands of type 'Point' and 'Point'The program does not compile. For a struct, C# does not know what == means until the struct declares that operator itself. Compare structs with Equals: m.Equals(n) gives true, because all the fields of both points are zero.
Key points
- For classes,
==andEqualscheck reference equality by default: whether it is one object. Equalson a struct compares all the fields, while==on a struct does not compile without a declaration of its own.- Two boxed numbers are two objects:
==givesfalse, andEqualsgivestrue. stringcompares the text with both==andEquals.