IComparable поведение для нулевых аргументов
Я реализую IComparable
а также IComprable<T>
в одном из моих классов. Есть ли какие-либо рекомендации о том, как CompareTo
метод в каждом случае должен вести себя, когда задан нулевой аргумент? Должен ли он вернуть положительное число или бросить ArgumentNullException
? Или это поведение может варьироваться в зависимости от класса реализации?
Я видел документацию MSDN ( здесь и здесь), но по этому вопросу ничего не сказано. Любая помощь будет оценена.
3 ответа
Обе ссылки MSDN для IComparable.CompareTo()
а также IComparable<T>.CompareTo()
заявить следующее:
По определению любой объект сравнивается больше чем (или следует)
Nothing
и две нулевые ссылки сравниваются равными друг другу.
Nothing
в VB соответствует null
в C#.
Обратите внимание, что в предыдущем абзаце говорится:
Смысл сравнений "меньше чем", "равно" и "больше чем" зависит от конкретной реализации.
Но ссылки на экземпляры, которые не являются нулевыми, всегда больше, чем нулевые ссылки, независимо от того, как вы сравниваете экземпляры вашего класса.
Я видел документацию MSDN, но по этому вопросу ничего не сказано
Да, но не очень ясно. В документации говорится:
По определению, любой объект сравнивает больше (или следует) Ничто, а две нулевые ссылки сравниваются равными друг другу.
Документация сбивает с толку, потому что она смешивает идиомы из C# (null) и VB (Nothing) в одном предложении. Я упомяну это менеджеру документации.
Обратите внимание, что то же правило применяется к типам значений, допускающих значение NULL. Например, если вы сортируете список целых чисел, допускающих значение NULL, то для целей сортировки 1 считается больше нуля. Быть осторожен; это не то, как по умолчанию в C# сравниваются обнуляемые целые числа.
Убедитесь, что вы используете Object.ReferenceEquals, чтобы проверить, является ли аргумент, переданный CompareTo, нулевым. Избегайте использования операторов == и!= В методах CompareTo, потому что кто-то может фактически следовать предложению MSDN о делегировании этих операторов обратно в метод CompareTo, который, в свою очередь, создал бы бесконечный цикл и переполнение стека (!) В мгновение ока.
Вот модель, как вы можете попытаться реализовать метод CompareTo:
public class Piano : IComparable<Piano>
{
public float Mark { get; set; }
public int CompareTo(Piano other)
{
// The very basic implementation of CompareTo
if (object.ReferenceEquals(other, null))
return 1; // All instances are greater than null
return Mark.CompareTo(other.Mark);
}
}
Весь исходный код с пояснениями по этому адресу.