Правильное внедрение IComparable <T>в Struct в C # 8 с включенным Nullable для включения - PullRequest
2 голосов
/ 01 октября 2019

Какой теперь правильный способ реализовать CompareTo в C # 8, когда Nullable включен. Функция реализованного интерфейса в Visual Studio предложила эту сигнатуру:

public struct PackageVersionNumber : IComparable<PackageVersionNumber>
{
    public int Major { get; }

    public int Minor { get; }

    public int Patch { get; }

    public int CompareTo([AllowNull] PackageVersionNumber other)
    {
        // ...
    }
}

PackageVersionNumber в этом случае является структурой и на самом деле не должен быть нулевым. Могу ли я безопасно удалить атрибут [AllowNull] из аргумента или мне нужно оставить его там и действительно проверить на ноль. Или это ошибка?

1 Ответ

3 голосов
/ 01 октября 2019

TL; DR
Вы можете безопасно удалить этот атрибут из подписи метода.

Пояснение

В вашем CompareToподпись метода, структура передается по значению и не помечается как обнуляемая. Это правильная реализация интерфейса для вашей PackageVersionNumber struct.

Это означает, что значение аргумента other не может быть null независимо от того, что вы делаете.

Вы даже не можете писать if (other == null) - это приведет к ошибке компилятора (если, между прочим, вы не перегружаете оператор == для PackageVersionNumber, что, кстати, вы должны учитывать для структуры).

Но даже с перегруженным ==оператор, if (other == null) сравнение будет всегда выход false - так что нет необходимости в этой проверке. Перегруженный оператор позволит компилятору неявно приводить PackageVersionNumber к нулю PackageVersionNumber? в сравнении - и вы получите предупреждение CS0472:

Результатом выражения всегда является 'ложь'поскольку значение типа «PackageVersionNumber» никогда не равно «нулю» типа «PackageVersionNumber?»

Я полагаю, что функция «Реализация интерфейса» в Visual Studio не учитывает тип, для которогоинтерфейс реализован и всегда использует один и тот же фрагмент кода с AllowNullAttribute.

Этот атрибут действительно полезен для реализации интерфейса для необнуляемых ссылочных типов. Хотя они «логически» не обнуляются, все еще есть способ получить значение null во время выполнения - так что нулевая проверка необходима, чтобы избежать NullReferenceException. Кроме того, вы должны обеспечить обратную совместимость со сборками, скомпилированными с C # 7.x и ниже - IComparable<T> отлично допускает null для T s, которые являются ссылочными типами.

...