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 asobject
, or asFoo
. Since you use anobject
, the only binding at compile time C# can make is the one with reference equality.
It's because the System.Object
implementation of ==
tests reference equality, like the static Equals(object, object)
, while instance Equals(object)
is overloaded, so it checks the actual value.
When you box a value type twice, you get two different instances, so of course reference equality fails.
The operator, being static, is bound at compile time, so there is no dynamic dispatch. Even with strings, which are already reference types and are therefore not boxed when assigned to an object-type variable, you can get an unintended reference comparison with the == operator if one of the operands has a static type other than string
.
The operator ==
is like an overloaded static function selected based on the compile time types. In your case the type of the values is Object
, for which the ==
operator implements reference equality.
On the other hand .Equals
is virtual and overridden, so it will do the comparison based on the actual types.
来源:https://stackoverflow.com/questions/34459299/why-does-not-work-while-comparing-two-object-type-variables-boxed-with-same-i