IEqualityComparer для обнуляемой структуры

Я хочу написать сравнитель равенства для структур Nullable. Допустим, DateTime?, Итак, я придумаю этот код:

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();
    }
}

Компилятор не любит это и говорит мне:

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

Это четкое сообщение, однако Nullable<T> это класс, и TType? это просто сокращение для Nullable<TType>, Или я что-то упустил?

Почему это не работает? И есть ли решение иметь IEqualityComparer<T> использовать T.HasValue имущество?

1 ответ

Решение

Это довольно просто - Nullable<> это structтаким образом, он считается запечатанным классом, что запрещено в ограничении (очевидно - если вы используете запечатанный класс в качестве ограничения, нет необходимости использовать аргумент универсального типа - у вас уже всегда есть точно такой же тип).

Но вам не нужно делать это вообще. Просто иметь TType ограничен struct, но вместо того, чтобы использовать TEntityПросто используйте TType? всякий раз, когда вам нужен обнуляемый:

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();
    }
}

Как примечание, nullables уже имеют реализацию равенства, которая включает проверку на нулевые значения, так что если вы можете избежать всего этого, если вы знаете тип nullable во время компиляции.

Другие вопросы по тегам