IEqualityComparer for nullable structure

I want to write an equality mapper for Nullable structs. Let's say DateTime?

. So I came up with this code:

public class NullableEntityComparer<TEntity, TType> : IEqualityComparer<TEntity> 
        where TType : struct
        where TEntity : Nullable<TType>
{
    public bool Equals(TEntity x, TEntity y)
    {
        if(!x.HasValue && ! y.HasValue) return true;
        if(x.HasValue && y.HasValue) return x.Value == y.Value;
        return false;
    }

    public int GetHashCode(TEntity obj)
    {
        if (obj == null) throw new ArgumentNullException("obj");
        if (obj.HasValue) return obj.Value.GetHashCode();
        else return obj.GetHashCode();
    }
}

      

The compiler doesn't like this and tells me:

'TType?' is not a valid constraint. A type used as a constraint must be an interface, a non-sealed class or a type parameter.   

      

This is a clear message, however, it Nullable<T>

is a class and TType?

is just an abbreviation for Nullable<TType>

. Or am I missing something?

Why doesn't it work? And is there a solution to use the IEqualityComparer<T>

property T.HasValue

?

+3


source to share


1 answer


It's pretty simple - it Nullable<>

is struct

, so it is considered a closed class, which is forbidden in the constraint (obviously - if you use a closed class as a constraint, there is no need to use a generic type - you always have the same type already).

But you don't need to do this at all. Just TType

limited struct

, but instead of using, TEntity

just use TType?

whenever you need a nullable value:



public class NullableEntityComparer<TType> : IEqualityComparer<TType?> 
        where TType : struct
{
    public bool Equals(TType? x, TType? y)
    {
        if(!x.HasValue && ! y.HasValue) return true;
        if(x.HasValue && y.HasValue) return x.Value.Equals(y.Value);
        return false;
    }

    public int GetHashCode(TType? obj)
    {
        return obj.GetHashCode();
    }
}

      

As a side note, nullables already have an equality implementation that includes checking for nulls, so if you can avoid all of this if you know the type of NULL at compile time.

+5


source







All Articles