c# - 构造函数是在C#中初始化类中非空属性的唯一方法吗?

标签 c# nullable-reference-types non-nullable

我已切换为在使用C#8的项目中启用可空值。现在我有以下类(class):

public class Request
{
    public string Type { get; set; }
    public string Username { get; set; }
    public string Key { get; set; }
}

编译器当然会提示不能保证这些属性不会为null。除了添加一个接受不可为空的字符串的构造函数外,我没有其他任何方法可以确保这一点。

对于一个小类来说,这似乎很好,但是如果我有20个属性,这是在构造函数中列出所有属性的唯一方法吗?是否有可能以某种方式使用初始化程序强制执行:
var request = new Request { Type = "Not null", Username = "Not null" }; // Get an error here that Key is null

P.S.有一个很好的答案建议对属性使用iniatlizer,但这并不总是有效的,例如适用于例如Type,一个人不能只是初始化为某个随机值

最佳答案

对象初始化器语法实际上只是显式分配给字段或属性 setter 的简写形式,即

var request = new Request { Type = "Not null", Username = "Not null" };

等效于:
var request = new Request();   // <-- All properties are default
request.Type = "Not null";     // <-- Type and key are default
request.Username = "Not null"; // <-- Key is still default

如您所见,Request实例仍会经历几种状态,其中属性处于默认状态,除非您在构造函数中分配了其他默认值,否则其他类型的引用类型(如字符串)将为null

另外,通过指定不同的默认值
public string Type { get; set; } = ""
public string Username { get; set; } = "";
public string Key { get; set; } = "";

等效于在默认构造函数中分配这些值,即
public Request()
{
    Type = "";
    UserName = "";
    Key = "";
}

可以想象,如果您随后立即使用对象初始化程序语法再次更改该值,那将有点浪费。

或者,如果您不需要可变的类,我建议您提供一个或多个构造函数重载,然后为任何缺失的字段提供合适的非null默认值,然后使属性不可变,例如
public class Request
{
    public Request(string type = "", string userName = "", string key = "")
    {
         Type = type;
         Username = userName;
         Key = key;
    }

    public string Type { get; }     // <-- No setter = immutable.
    public string Username { get; }
    public string Key { get; }
}

现在,您可以实例化该类,而无需经历任何属性都为null的状态,也不需要中间默认赋值的开销,例如
var myRequest = new Request(key: "SomeKey"); // <-- Username and Type are defaulted to ""

关于c# - 构造函数是在C#中初始化类中非空属性的唯一方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59530963/

相关文章:

c# - 使用 Twitter API 1.1 oAuth 验证和请求用户的时间线

c# - 使用参数验证初始化可变不可空属性时避免 CS8618 警告

c# - 可空引用类型和本地函数 - 它们可以很好地协同工作吗?

jvm - 在 Kotlin 中,如何惯用地访问可为空的嵌套映射值,或返回默认值?

java - 如何摆脱 TreeMap 的 eclipse neon 中的 "Null type safety"警告

c# - 无法将类型 'System.Linq.IQueryable<int>' 转换为 'int'

C# 日期时间操作

c# - 字段的自定义属性

c# - 为什么 "where T : object"的类型约束没有在 C# 8 中编译

kotlin - 如何处理不为null的可为空的变量?