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 во время компиляции.