IEnumerable<T>: Can use Equals method but not equality operator
public static IEnumerable<T> Method<T>(IEnumerable<T> iterable){
T previous = default(T);
foreach(T current in iterable){
if (!current.Equals(previous)){
previous = current;
yield return current;
}
}
}
I don't have any questions about this code, but just why if it is possible to compare two objects of type T using:
if (!current.Equals(previous))
Then why is it not possible to compare using:
if (!current == previous)
The ! gives you an error saying
Operator '!' cannot be applied to operand of type 'T'
And if you remove that you get:
Operator '==' cannot be applied to operands of type 'T' and 'T'
I gave up on a code challenge because it seemed to be telling me you literally can't compare one T to another. Then I found out you can do that but just with different syntax/using a specific method.
Can anyone advise why this would be please?
Solution 1:
.Equals
is a part of System.Object
. Right now there is no way to constrain a generic to have support for a specific operator overloading. You can however use IEquatable<T>
or IEqualityComparer<T>
to ensure the type implements its definition of equality.
Solution 2:
See this section of the language specification where ==
is specified. You can see that the language only has these overloads of ==
predefined:
bool operator ==(int x, int y);
bool operator ==(uint x, uint y);
bool operator ==(long x, long y);
bool operator ==(ulong x, ulong y);
bool operator ==(float x, float y);
bool operator ==(double x, double y);
bool operator ==(decimal x, decimal y);
bool operator ==(bool x, bool y);
bool operator ==(E x, E y); // for every enum E
bool operator ==(C x, C y); // for every class C
bool operator ==(string x, string y);
bool operator ==(System.Delegate x, System.Delegate y);
The type parameter T
in your method is not constrained to anything, so what if it is, for example, a struct type? As you can see from the above list, there are no ==
operators defined for an arbitrary struct type.
If you add a T: class
constraint, then you would be able to use ==
on it, because there is a ==
operator for all classes.
On the other hand, there is an Equals
method declared in System.Object
, from which every type in C# inherits from. Therefore, it is possible to use Equals
on values of type T
, even when T
can be any type.