满足或静音可为空的泛型类型属性警告

时间:2019-12-06 14:43:31

标签: c# generics nullable c#-8.0 nullable-reference-types

在C#8.0中,使用给定的简化代码,可以使用可为空的引用类型,其中T可以是任何值类型或引用类型,而空值是引用类型T实例的有效值:

public class C<T>
{
    public T P { get; set; }
}

编译器发出警告 CS8618 "Non-nullable property 'P' is uninitialized. Consider declaring the property as nullable." 。 我该如何满足编译器的要求并静音此警告(不抑制CS8618)?

是否存在我可以应用的属性或类型参数约束?在那种情况下怎么办?

我想出的最好的方法是

public T P { get; set; } = default!;

但是我希望找到一种方法,而无需使用“ dammit运算符”('!')。

注意:您不能将属性的类型声明为T?-CS8627。此外,这意味着返回的任何值类型都是Nullable<T>,这不是预期的。


编辑:我注意到这也可以:

public class C<T>
{
    public C()
    {
        P = default;
    }
    [AllowNull]
    public T P { get; set; }
}

但是我更喜欢使用自动属性初始化程序。

2 个答案:

答案 0 :(得分:1)

classstruct的可空性基本上是不兼容的,不能组合。

您的选择包括:

  • 使您的课程完全通用;因此,您的班级内TT?之间没有区别。仍然允许C<int>C<int?>,但不允许T?

  • 根据您的要求约束为classstruct

  • 编写两个单独的类,一个用于结构,一个用于引用类型。

编写两个足够简单的类也不错。您也许可以将非泛型部分推入基类,以避免过多的重复。

答案 1 :(得分:0)

实例化类时,属性P的值为空,这就是您看到警告的原因。

实例化类时,需要确保该值不为null,唯一的方法是定义一个构造函数并为P提供值。由于T是通用类型,因此您有两个选择:

  1. 将值作为构造函数参数传递或
  2. 约束T以便能够创建新实例
// Option #1
public class C<T>
{
   C(T p)
   {
       P = p
   }

   public T P { get; set; }
}

// option #2:
public class C<T> where T : new()
{
   C()
   {
       P = new T()
   }

   public T P { get; set; }
}