如何在C#7中使用可空引用类型属性

如何在C#7中使用可空引用类型属性,c#,attributes,nullable-reference-types,C#,Attributes,Nullable Reference Types,我有一个作为源代码分发的库,我不能强迫我的用户使用C版本8 我仍然希望为使用C#8和可空引用类型的用户改善体验 或者换句话说:我的库必须用C#7编译,但也包括关于可空引用类型的信息 到目前为止,我所做的是定义属性,MaybeNull等,我的源文件以 #if (NETSTANDARD && !NETSTANDARD2_0 && !NETSTANDARD1_6) || (NETCOREAPP && !NETCOREAPP2_0 && !

我有一个作为源代码分发的库,我不能强迫我的用户使用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) ...
这是可行的,但因为我不能使用
有几件事我还没有找到解决方案

  • 泛型
    ,似乎没有办法用属性将泛型类型参数标记为可空。i、 e.
    公共异步任务方法的属性版本(KeyValuePair数据)
  • 属性和字段上的属性在类内部被忽略(但从外部工作)
  • 关于局部变量的警告
    stringlocal=null

nullable disable warnings
为我的用户解决了最后2个问题,因此这并不重要,但泛型是一个问题,因为我有很多异步方法是否有一种方法可以在泛型中标记可为null的引用类型而不使用

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

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

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


总之,您应该能够使用
#if
/
#endif
之类的东西。

你是说用
可空的
而不是
ᴇM、 Nullable仅适用于值类型。我指的是可空引用类型,这是C语言中的一个新特性#8@MatthewWatson,这只是一个带有属性的包(我已经得到了)。它没有说明如何在泛型中使用它们。您能否定义自己版本的
NullableAttribute
,并手动应用它?谢谢您的回答,但我的库是作为源代码分发的。那么我认为使用
#if
/
#endif
的条件编译是您唯一的选择。不久前,当NRT是新的(可能是预发行版,我不太记得了)时,可以在内部定义自己的
System.Runtime.CompilerServices.NullableContextAttribute
和friends,然后手动将它们应用到API中,但现在可以得到CS8335。如果有用的话,下面是一个注释库的示例,它可以以向后兼容的方式作为源代码共享:很高兴知道我不是唯一一个遇到这个问题的人:-)。他们的解决方案是
#如果
围绕每个?还有!这对我来说是不值得的。无论如何,谢谢你。就xunit的断言而言,至少在我看来,这是值得的。然后我又是他们:)。这里没有很多方法可以注释,而且它们的应用非常广泛。如果你有更多的表面积或更少的消费者,我会认为这是不值得的。
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
    }
}