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

    }

}

Весь исходный код с пояснениями по этому адресу.

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