I'm trying to embrace C# 8's nullable references types in my project and make it smoothly work with EF Core.
Following this guide , I made my entity classes have constructors accepting all data needed for initializing their non-nullable properties:
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; }
}
In my business case I sometimes need to update all properties of the entity. I can use property setters, but since I want to make sure I don't omit anything by doubling the initialization syntax (and in reality my entities can have 10 or more properties), I decided to create a public Update() function for convenience and call it instead of constructor body:
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;
}
Now, when creating the entity, I call the constructor, and when changing it, I call Update(). However, now the compiler gives nullability warning (CS8618) that the non-nullable properties are not initialized by the constructor . It's apparently unable to guess that calling Update will initialize them.
I've maybe overengineered it a bit with this Update() method, but now I'm curious is there a way to make the compiler trust that my constructor will initialize the properties ?
It is indeed a bit verbose, but you can use the [MemberNotNull]
attribute in .NET 5 to tell the compiler that a method ensures a member is not null after it returns.
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;
}
}
If you are sure what you are doing, then you can suppress compiler warning by
#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
also there is an open case for that in github , you can check it. You can use the approach below (quoted from 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;
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.