可空引用类型和构造函数警告

Пав*_*вле 7 c# constructor entity-framework-core c#-8.0 nullable-reference-types

我正在尝试在我的项目中包含 C# 8 的可为空引用类型,并使其与 EF Core 顺利工作。

按照本指南,我使我的实体类具有接受初始化其不可为空属性所需的所有数据的构造函数:

public class MyEntity
    {
        public MyEntity(int someNumber, string name, string shortName, bool active)
        {
            SomeNumber= someNumber;
            Name = name;
            ShortName = shortName;
            Active = active;
        }

        public int SomeNumber { get; set; }
        public string Name { get; set; }
        public string ShortName { get; set; }
        public string? SomethingOptional { get; set; }
        public bool Active { get; set; }
    }
Run Code Online (Sandbox Code Playgroud)

在我的业务案例中,我有时需要更新实体的所有属性。我可以使用属性设置器,但由于我想通过将初始化语法加倍来确保不会遗漏任何内容(实际上我的实体可以有 10 个或更多属性),我决定创建一个公共 Update() 函数以方便使用并调用它而不是构造函数体:

        public MyEntity(int someId, string name, string shortName, bool active)
        {
            Update(someId, name, shortName, active);
        }

        public void Update(int someId, string name, string shortName, bool active)
        {
            SomeNumber = someId;
            Name = name;
            ShortName = shortName;
            Active = active;
        }
Run Code Online (Sandbox Code Playgroud)

现在,在创建实体时,我调用构造函数,而在更改它时,我调用 Update()。 但是,现在编译器会发出可空性警告 (CS8618),提示不可空属性未由构造函数初始化。显然无法猜测调用 Update 会初始化它们。

我可能使用 Update() 方法对它进行了一些过度设计,但现在我很好奇有没有办法让编译器相信我的构造函数将初始化属性

Rik*_*son 25

它确实有点冗长,但是您可以使用[MemberNotNull].NET 5中的属性来告诉编译器,一个方法确保成员在返回后不为空。

using System.Diagnostics.CodeAnalysis;
    
public class MyEntity
{
    [MemberNotNull(nameof(Name), nameof(ShortName))]
    public void Update(int someId, string name, string shortName, bool active)
    {
        SomeNumber = someId;
        Name = name;
        ShortName = shortName;
        Active = active;
    }
}
Run Code Online (Sandbox Code Playgroud)


Der*_*ğlu 0

如果您确定自己在做什么,那么您可以通过以下方式抑制编译器警告

#pragma warning disable CS8618
public MyEntity(int someNumber, string name, string shortName, bool active)
{
    SomeNumber= someNumber;
    Name = name;
    ShortName = shortName;
    Active = active;
}
#pragma warning disable CS8618
Run Code Online (Sandbox Code Playgroud)

github上也有一个开放的案例,你可以查看它。您可以使用下面的方法(引用自github)

class MyClass
{
    private string m_str1;
    private string m_str2;

    public MyClass()
    {
        Init(out m_str1, out m_str2);
    }

    private void Init(out string str1, out string str2)
    {
        str1 = string.Empty;
        str2 = string.Empty;
    }
}
Run Code Online (Sandbox Code Playgroud)