According to the documentation of the ==
operator in MSDN,
For predefined value types, the equality operator (==) returns true if th
There is an MSDN Connect entry for this here
Alex Turner's reply starts with:
Unfortunately, this behavior is by design and there is not an easy solution to enable use of == with type parameters that may contain value types.
bool Compare(T x, T y) where T : class { return x == y; }
The above will work because == is taken care of in case of user-defined reference types.
In case of value types, == can be overridden. In which case, "!=" should also be defined.
I think that could be the reason, it disallows generic comparison using "==".
The .Equals()
works for me while TKey
is a generic type.
public virtual TOutputDto GetOne(TKey id)
{
var entity =
_unitOfWork.BaseRepository
.FindByCondition(x =>
!x.IsDelete &&
x.Id.Equals(id))
.SingleOrDefault();
// ...
}
Well in my case I wanted to unit-test the equality operator. I needed call the code under the equality operators without explicitly setting the generic type. Advises for EqualityComparer
were not helpful as EqualityComparer
called Equals
method but not the equality operator.
Here is how I've got this working with generic types by building a LINQ
. It calls the right code for ==
and !=
operators:
/// <summary>
/// Gets the result of "a == b"
/// </summary>
public bool GetEqualityOperatorResult<T>(T a, T b)
{
// declare the parameters
var paramA = Expression.Parameter(typeof(T), nameof(a));
var paramB = Expression.Parameter(typeof(T), nameof(b));
// get equality expression for the parameters
var body = Expression.Equal(paramA, paramB);
// compile it
var invokeEqualityOperator = Expression.Lambda<Func<T, T, bool>>(body, paramA, paramB).Compile();
// call it
return invokeEqualityOperator(a, b);
}
/// <summary>
/// Gets the result of "a =! b"
/// </summary>
public bool GetInequalityOperatorResult<T>(T a, T b)
{
// declare the parameters
var paramA = Expression.Parameter(typeof(T), nameof(a));
var paramB = Expression.Parameter(typeof(T), nameof(b));
// get equality expression for the parameters
var body = Expression.NotEqual(paramA, paramB);
// compile it
var invokeInequalityOperator = Expression.Lambda<Func<T, T, bool>>(body, paramA, paramB).Compile();
// call it
return invokeInequalityOperator(a, b);
}
In general, EqualityComparer<T>.Default.Equals
should do the job with anything that implements IEquatable<T>
, or that has a sensible Equals
implementation.
If, however, ==
and Equals
are implemented differently for some reason, then my work on generic operators should be useful; it supports the operator versions of (among others):
So many answers, and not a single one explains the WHY? (which Giovanni explicitly asked)...
.NET generics do not act like C++ templates. In C++ templates, overload resolution occurs after the actual template parameters are known.
In .NET generics (including C#), overload resolution occurs without knowing the actual generic parameters. The only information the compiler can use to choose the function to call comes from type constraints on the generic parameters.