C#8是否注释了可空属性和参数?

Max*_*oro 4 c# c#-8.0 nullable-reference-types

我很好奇可引用的引用类型是如何工作的,不是在你自己的代码库中,而是在已编译的库中.C#是否能够知道属性或参数是否可为空,或许可以检查一些编译器添加属性的存在性?

svi*_*ick 6

是的,如果库是使用打开了可空引用类型的C#8.0编译器编译的,则编译器将能够识别哪些值被标记为可为空.

例如,考虑以下代码:

class C
{
    string NotNullProperty { get; set; }
    string? NullProperty { get; set; }

    void M(string notNullParameter, string? nullParameter) {}
}
Run Code Online (Sandbox Code Playgroud)

它大致编译成:

[NonNullTypes(true)]
class C
{
    string NotNullProperty { get; set; }

    [Nullable]
    string NullProperty { get; set; }

    void M(string notNullParameter, [Nullable] string nullParameter) { }
}
Run Code Online (Sandbox Code Playgroud)

请注意,可空属性和参数被标记为[Nullable]并且整个类被标记为[NonNullTypes(true)],表示为其启用了可为空的引用类型功能.

另一方面,如果代码是在没有该功能的情况下编译的,那么它将被视为"无视遗忘".这意味着当您使用该代码时,编译器不会产生与null相关的警告.


Jon*_*eet 5

似乎行为在VS2019 Preview 1和Preview 2之间已更改,可能是由于可以更改可为空的上下文的方式。不再有按装配或按类型的属性。当然,它可能会再次改变,

在VS2019 Preview 2中,表示可为空或不可为空的信息(参数和返回类型)的成员的每个部分(NullableAttribute如果需要的话)都使用包含在程序集本身中的a 进行单独分配。此属性具有两个构造函数:

NullableAttribute(byte)
NullableAttribute(byte[])
Run Code Online (Sandbox Code Playgroud)

byte当该参数/返回类型的可空性的每个方面都相同时,将使用该形式。的byte[],当有非空的单个元件的混合物被使用,由于泛型或阵列。在这两种情况下,1表示“不可为空”,2表示为“可为空”。因此,例如:

public class Test
{
    public string? Foo(string input) { ... }

    public List<string>? Bar() { ... }
}
Run Code Online (Sandbox Code Playgroud)

编译为:

public class Test
{
    [return:Nullable(2)]
    public string Foo([Nullable(1)] string input) { ... }

    [return: Nullable(new byte[] { 1, 2 })]
    public List<string> Bar() { ... }
}
Run Code Online (Sandbox Code Playgroud)

这样,任何检查程序集的代码(无论是使用该程序集作为参考的编译器,还是其他工具)都可以了解每个成员的意图。

我已经在博客文章中写了更多有关此的内容,但这应该足以理解要点。