У меня есть настраиваемая общая структура данных, которая включает метод Find:
public bool Find(TValue value, IEqualityComparer<TValue> comparer)
{
foreach (var x in items)
{
if (comparer.Equals(value, x))
return true;
}
return false;
}
Недавно я получил сообщение от клиента, который сказал, что это приводит к тому, что его компаратор равен throw NullReferenceException, если value is null или если один из элементов в коллекции null.
Мой первоначальный ответ заключался в том, что его реализация IEqualityComparer<T>.Equals была ошибочной, потому что она не грамотно обрабатывает значения null. Но я не смог найти какую-либо документацию, чтобы явно поддержать меня. У меня есть некоторые доказательства, указывающие, что я прав, но ничего явно.
Во-первых, кажется глупым, что я бы изменил этот простой вызов comparer.Equals на:
if (x == null)
{
if (value == null)
return true;
}
else if (value != null && comparer.Equals(value, x))
return true;
Во-вторых, документация для Object.Equals говорит, среди прочего:
-
x.Equals(null)возвращаетfalse. - Реализации
Equalsне должны генерировать исключения.
Это, для меня, является убедительным доказательством того, что IEqualityComparer <T> .Equals должен изящно обрабатывать нулевые параметры.
Другие доказательства того, что документация для IComparer.Compare говорит:
Разрешается сопоставление нуля с любым ссылочным типом и не выполняется генерировать исключение. Нулевая ссылка считается меньшей, чем любая ссылка, которая не является нулевой.
Можно было бы ожидать, что IEqualityComparer<T>.Equals будет действовать аналогичным образом. Интересно отметить, однако, что пример, приведенный на этой странице, будет бросать NullReferenceException, если любой параметр null.
Я прошел через документацию для Object.Equals, IEquatable<T>, IEqualityComparer<T> и IEqualityComparer, а также бесчисленные сообщения в блогах, статьи и вопросы SO. Ничто не дает каких-либо конкретных рекомендаций о том, как обрабатывать параметры null.
Существуют ли такие руководящие принципы? Если нет, что рекомендуют гуру и почему?