While trying to implement a simple singly linked list in C#, I noticed that ==
does not work while comparing two object type variables boxed with an int value but .Equals
works.
Wanted to check why that is so.
The below snippet is a generic object type Data property
public class Node {
/// <summary>
/// Data contained in the node
/// </summary>
private object Data { get; set; };
}
The below code traverses the singly linked list and searches for a value of type object -
/// <summary>
/// <param name="d">Data to be searched in all the nodes of a singly linked list
/// Traverses through each node of a singly linked list and searches for an element
/// <returns>Node if the searched element exists else null </returns>
public Node Search(object d)
{
Node temp = head;
while (temp != null)
{
if (temp.Data.Equals(d))
{
return temp;
}
temp = temp.Next;
}
return null;
}
However, if I replace
temp.Data.Equals(d)
with temp.Data == d
it stops working even though temp.Data
and d
both have the value '3'. Any reasons why ==
does not work on object type variables?
Here's the snippet from the Main function -
SinglyLinkedList list = new SinglyLinkedList();
list.Insert(1);
list.Insert(2);
list.Insert(3);
list.Insert(4);
list.Insert(5);
list.Print();
Node mid = list.Search(3);
I believe since I am passing an int value 3
and the Search method expects an object type, it would have successfully boxed 3 as a object type. However, not sure why ==
doesn't work but .Equals
does.
Is ==
operator overloaded for value types only?
There are two reasons:
Equals
is not bounded with ==
and vice versa, and by default checks for reference-equality:
As you can read in the specifications of .Equals
vs ==
:
By default, the operator
==
tests for reference equality by determining if two references indicate the same object, so reference types do not need to implement operator==
in order to gain this functionality. When a type is immutable, meaning the data contained in the instance cannot be changed, overloading operator==
to compare value equality instead of reference equality can be useful because, as immutable objects, they can be considered the same as long as they have the same value. Overriding operator==
in non-immutable types is not recommended.Overloaded operator
==
implementations should not throw exceptions. Any type that overloads operator==
should also overload operator!=
.
Although the compiler will throw an error if you do not override the !=
as well, and will warn that you better override both .Equals
and .GetHashCode
.
So overriding/overloading the .Equals
, ==
and !=
are different things. Overriding .Equals
has no effect on overloading ==
and !=
. After all the ==
is a custom operator. Although it is not wise to do so, you could use it for another purpose than an equality check.
Furthermore operators are resolved at compile-time:
Take the following example the following csharp
interactive shell program:
$ csharp
Mono C# Shell, type "help;" for help
Enter statements below.
csharp> public class Foo {
>
> public int data;
>
> public static bool operator == (Foo f1, Foo f2) {
> return f1.data == f2.data;
> }
>
> public static bool operator != (Foo f1, Foo f2) {
>
> return f1.data != f2.data;
> }
>
> }
(1,15): warning CS0660: `Foo' defines operator == or operator != but does not override Object.Equals(object o)
(1,15): warning CS0661: `Foo' defines operator == or operator != but does not override Object.GetHashCode()
csharp> object f = new Foo();
csharp> object f2 = new Foo();
csharp> f == f2
false
csharp> Foo f3 = f as Foo;
csharp> Foo f4 = f2 as Foo;
csharp> f3 == f4
true
As you can see, ==
gives a different result if you call the objects as object
, or as Foo
. Since you use an object
, the only binding at compile time C# can make is the one with reference equality.