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

标签 c# attributes nullable-reference-types

我有一个作为源代码分发的库,我不能强制我的用户使用 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) ...

这行得通,但因为我不能使用 ?!有几件事我还没有找到解决方案

  • Generics ,似乎没有办法用属性将泛型类型参数标记为可为空。即 public async Task<string?> Method(KeyValuePair<string, string?> data) 的属性版本
  • 属性和字段的属性在类内部被忽略(但在外部有效)
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
    }
}
  • 警告本地人string local = null;等等

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

最佳答案

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

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

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

综上所述,您应该能够使用 ?! 并避免使用 #if/#endif 你提到的东西。

关于c# - 如何在 C#7 中使用可空引用类型属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60409751/

相关文章:

C# 8 - 枚举上的 CS8605 "Unboxing possibly null value"

c# - 在 ASP.NET 4.6 中使用 Serilog 启动 OWIN

c# - 如何创建 Func<TSource> 到 Expression<Func<TSource,TValue>>

android - 错误: No resource identifier found for attribute 'popupTheme' in package “com.example…”

javascript - 获取动态字符串的属性

HTML CSS 如何交换 css 属性

c# - 出于可空性分析目的,如何告诉 C# 结构的不可空字段实际上可能为空?

c# - 为什么我没有收到关于在 C# 8 中使用结构的类成员可能取消引用 null 的警告?

c# - 为什么我会收到 "The type parameter must be invariantly valid..."错误?

c# - 为什么要继续执行Task.WhenAll的延续?