首页 > 解决方案 > 如何在 C#7 中使用可为空的引用类型属性

问题描述

我有一个作为源代码分发的库,我不能强迫我的用户使用 C# 版本 8。

我仍然想改善使用 C# 8 和可为空引用类型的用户的体验。

或者换句话说:我的库必须使用 C# 7 编译,但还包含有关可为空引用类型的信息。

到目前为止我所做的是定义属性MaybeNull等,我的源文件以

#if (NETSTANDARD && !NETSTANDARD2_0 && !NETSTANDARD1_6) || (NETCOREAPP && !NETCOREAPP2_0 && !NETCOREAPP2_1 && NETCOREAPP2_2)
#nullable disable warnings
#endif

我已经在属性、参数返回类型等上添加了属性。

[return: MaybeNull]
public string Function([AllowNull) param) ...

这行得通,但由于我无法使用?,而且!我还没有找到解决方案

public class C {
    [AllowNull, MaybeNull]
    private string _field;

    [AllowNull, MaybeNull]
    public string Prop1 => _field; // CS8603, Possible null reference return

    [AllowNull, MaybeNull]
    public string Prop2 { get; set; }

    public C() { 
        // CS8618, Non-nullable property 'Prop2' is uninitialized
        // CS8618, Non-nullable field '_field' is uninitialized
    }
}

nullable disable warnings为我的用户解决了最后两点,所以这并不重要,但泛型是一个问题,因为我有很多异步方法。有没有办法在不使用的情况下在泛型中标记可为空的引用类型?

标签: c#attributesnullable-reference-types

解决方案


您可以使用 C# 8 编译您的库,并让其他人使用 C# 7(或更早版本)的这些二进制文件。限制因素不是语言而是框架(除非他们使用早期的编译器编译您的源代码)。

NRT 注释使用在生成的程序集中自动定义的属性。您通常不会看到这些,它们通过名称而不是 匹配Type,这意味着即使它们具有不同的注释类型(具有相同的知名名称),您也可以使用来自多个程序集的注释。

这与属性等不同,这些属性MaybeNull不是NotNullWhen由编译器生成的,但也与全名匹配,这意味着您可以自己定义它们或使用诸如Nullable.

话虽如此,您应该能够使用?!并避免#if/#endif您提到的东西。


推荐阅读