在 C# 8 的结构上正确实现 IComparable<T>,并将 Nullable 设置为启用

Properly implementing IComparable<T> on a Struct in C# 8 with Nullable set to enable

启用 Nullable 后,现在在 C# 8 中实现 CompareTo 的正确方法是什么。 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 在这种情况下是一个结构,实际上不应该为 null。我可以安全地从参数中删除 [AllowNull] 属性,还是需要将其保留在那里并真正检查是否为 null。或者这是一个错误?

TL;DR
您可以安全地从方法签名中删除此属性。

说明

在您的 CompareTo 方法签名中,结构按值传递并且未标记为可为空。这是您的 PackageVersionNumber 结构的正确接口实现。

也就是说,无论你做什么,other参数值都不能是null

你甚至不能写 if (other == null) - 这会产生编译器错误(除非你为 PackageVersionNumber 重载 == 运算符,顺便说一句,你应该真正考虑结构).

但即使使用重载的 == 运算符,if (other == null) 比较也会 总是 产生 false - 所以没有必要这样做查看。重载运算符将允许编译器在比较中将 PackageVersionNumber 隐式转换为可为空的 PackageVersionNumber? - 您将收到 CS0472 警告:

The result of the expression is always 'false' since a value of type 'PackageVersionNumber' is never equal to 'null' of type 'PackageVersionNumber?'

我想 Visual Studio 中的 "Implement interface" 特性没有考虑实现接口的类型,并且总是使用与 AllowNullAttribute 相同的片段。

该属性对于实现不可为 null 的引用类型的接口确实很有用。虽然它们 "logically" 不可为 null,但仍有一种方法可以在运行时获取 null 值 - 因此需要进行 null 检查以避免 NullReferenceException。此外,您必须确保与使用 C#7.x 及更低版本编译的程序集的向后兼容性 - IComparable<T> 完全允许 ​​null 用于 T 引用类型。