我正在尝试在我的项目中采用 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; }
}
在我的业务案例中,我有时需要更新实体的所有属性。我可以使用属性设置器,但由于我想确保不会通过加倍初始化语法来省略任何内容(实际上我的实体可以有 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;
}
现在,在创建实体时,我调用构造函数,在更改实体时,我调用 Update()。
但是,现在编译器会给出可空性警告 (CS8618),指出不可空属性未由构造函数初始化。显然无法猜测调用 Update 会初始化它们。
我可能用这个 Update() 方法对它进行了一些过度设计,但现在我很好奇有没有办法让编译器相信我的构造函数会初始化属性?
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;
}
}
#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
github 上也有一个开放的case
,你可以查看一下。你可以使用下面的方法(引用自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;
}
}
public class MyEntity
{
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;
}
public int SomeNumber { get; set; }
// initialize an empty string to get rid of the warning
public string Name { get; set; } = string.Empty;
// initialize an empty string to get rid of the warning
public string ShortName { get; set; } = string.Empty;
public string? SomethingOptional { get; set; }
public bool Active { get; set; }
}