简体   繁体   English

正确实施 IComparable<t> 在 C# 8 中的结构上,将 Nullable 设置为启用</t>

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

What is now the proper way to implement CompareTo in C# 8 when Nullable is enabled.现在启用 Nullable 时,在 C# 8 中实现 CompareTo 的正确方法是什么。 The implement interface feature in Visual Studio suggested this signature: 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 is a struct in this case and really shouldn't be null. PackageVersionNumber 在这种情况下是一个结构,实际上不应该是 null。 Can I safely delete the [AllowNull] attribute from the argument or do I need to leave it there and really check for null.我可以安全地从参数中删除[AllowNull]属性,还是需要将其保留在那里并真正检查 null。 Or is this a bug?或者这是一个错误?

TL;DR TL;博士
You can safely remove this attribute from the method signature.您可以安全地从方法签名中删除此属性。

Explanation解释

In your CompareTo method signature, the struct is passed by-value and is not marked as nullable.在您的CompareTo方法签名中,该结构是按值传递的,并且未标记为可为空。 This is the correct interface implementation for your PackageVersionNumber struct.这是PackageVersionNumber结构的正确接口实现。

That means, the other argument value cannot be null no matter what you do.这意味着,无论您做什么, other参数值都不能是null

You cannot even write if (other == null) - that will produce a compiler error (unless you overload the == operator for PackageVersionNumber what you should really consider for a struct, by the way).你甚至不能写if (other == null) - 这会产生编译器错误(除非你为PackageVersionNumber重载==运算符,顺便说一下你应该真正考虑的结构)。

But even with an overloaded == operator, the if (other == null) comparison will always yield false - so there is no need in that check.但即使使用重载的==运算符, if (other == null)比较总是会产生false - 所以不需要检查。 The overloaded operator will allow the compiler to implicitly cast PackageVersionNumber to nullable PackageVersionNumber?重载运算符将允许编译器将PackageVersionNumber隐式转换为可为空PackageVersionNumber? in the comparison - and you'll get a CS0472 warning:在比较中 - 你会得到一个 CS0472 警告:

The result of the expression is always 'false' since a value of type 'PackageVersionNumber' is never equal to 'null' of type 'PackageVersionNumber?'表达式的结果始终为“假”,因为“PackageVersionNumber”类型的值永远不会等于“PackageVersionNumber?”类型的“null”。

I suppose that the "Implement interface" feature in Visual Studio doesn't consider the type on which the interface is implemented and always uses the same snippet with that AllowNullAttribute .我想 Visual Studio 中的“实现接口”功能不考虑实现接口的类型,并且始终使用与AllowNullAttribute相同的代码段。

That attribute is indeed useful for implementing the interface for non-nullable reference types.该属性对于实现不可为空的引用类型的接口确实很有用。 While they are "logically" non-nullable, there is still a way to get a null value at runtime - so a null check is required to avoid a NullReferenceException .虽然它们是“逻辑上”不可为空的,但仍有一种方法可以在运行时获取null值 - 因此需要进行 null 检查以避免NullReferenceException Furthermore, you have to ensure the backwards compatibility with assemblies compiled with C#7.x and below - IComparable<T> perfectly allows null for T s that are reference types.此外,您必须确保与使用 C#7.x 及更低版本编译的程序集的向后兼容性 - IComparable<T>完全允许null用于引用类型的T

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM