如何告诉编译器必须初始化 属性

how to tell compiler that property MUST be initialized

我有一个 class 比如这个:

public class Foo
{
    public string Bar { get; init; }
    public IImmutableSet<int> Baz { get; init; }
}

当我那样写的时候,我得到一个编译器警告

Non-nullable property 'Bar' must contain a non-null value when exiting constructor. Consider declaring the property as nullable. csharp(CS8618)

有很多内容解决这个问题(例如 ),但据我所知,它只是关于如何通过设置默认值或关闭编译器来消除消息使用 null!.

等“假默认值”的警告

但就我而言,默认值没有意义。 相反,我想告诉编译器必须显式设置这些属性,这样如果在使用对象之前没有设置任何属性,编译器就会抱怨。就像未赋值局部变量的情况一样:

这可能吗,如果可以,怎么办?

我知道我可以只定义一个带参数的构造函数,因此使用该构造函数是创建新实例的唯一方法。但是因为我有很多像上面那样的 classes,所以我需要写很多额外的代码(即构造函数)。如果有一种“必须初始化”标志,我的代码的读者也会更清楚。

使属性具有私有设置函数,并创建一个构造函数,您可以在其中设置这些私有 属性 值。

我可以使用 positional records:

public class Foo(string Bar, IImmutableSet<int> Baz);

我会在这一行中同时获得属性和构造函数。 但这只有在我需要值语义时才有意义。

我认为 get; 只有具有构造函数的属性才是可行的方法。

public class C
{
    public C(string a)
    {
        A = a;
    }

    public string A { get; }
}

I would need to write quite of lot of extra code (i.e. the constructors).

现在创建构造函数非常容易。需要:

  • Ctrl+. + 在 VS Code 中单击鼠标 1 次:

  • Ctrl+. + 向下箭头 + 在 VS 中输入:


微软怎么说?

1。 Working with Nullable Reference Types

In Working with Nullable Reference Types in Non-nullable properties and initialization shows 3 options:

一个。构造函数

Constructor binding is a useful technique to ensure that your non-nullable properties are initialized:

b。可为空的支持字段

Unfortunately, in some scenarios constructor binding isn't an option; navigation properties, for example, cannot be initialized in this way. (...) One way to deal with these scenarios, is to have a non-nullable property with a nullable backing field: C#

private Address? _shippingAddress;

public Address ShippingAddress
{
    set => _shippingAddress = value;
    get => _shippingAddress
           ?? throw new InvalidOperationException("Uninitialized property: " + > nameof(ShippingAddress));
}

c。强制初始化为null!

作为一个更简洁的替代方案,可以借助 null-forgiving 运算符 (!):

将 属性 简单地初始化为 null

C#

public Product Product { get; set; } = null!;

An actual null value will never be observed except as a result of a programming bug, e.g. accessing the navigation property without properly loading the related entity beforehand.

2。 Learn techniques to resolve nullable warnings

Learn techniques to resolve nullable warnings 中同样没有 get; init; 属性的示例,文章建议了两个选项来处理警告:

  • 构造函数
  • 初始化为null!;

    to indicate that a member is initialized in other code.

3。 Attributes for null-state static analysis interpreted by the C# compiler

对于更复杂的场景,可能值得查看 Attributes for null-state static analysis interpreted by the C# compiler 并使用一些可用的属性。不过,我认为这不是日常代码的路径。