I have switched to enable nullable in my project that uses C#8. Now I have the following class:
public class Request
{
public string Type { get; set; }
public string Username { get; set; }
public string Key { get; set; }
}
Compiler of course complains that it cannot guarantee that these properties won't be null. I can't see any other way of ensuring this than adding a constructor that accepts non-nullable strings.
This seems fine for a small class, but if I have 20 properties, is this the only way to list them all in a constructor? Is it possible somehow to e.g. enforce it with the initializer:
var request = new Request { Type = "Not null", Username = "Not null" }; // Get an error here that Key is null
P.S. There is a good answer that suggests using iniatlizer for properties, but that does not always work e.g. for types like e.g. Type
that one cannot just intialize to some random value
Object initializer syntax is really just short-hand for explicitly assigning to fields or property setters, i.e.
var request = new Request { Type = "Not null", Username = "Not null" };
Is equivalent to:
var request = new Request(); // <-- All properties are default
request.Type = "Not null"; // <-- Username and key are default
request.Username = "Not null"; // <-- Key is still default
As you can see, the Request
instance still goes through several states where the properties are in a default status, which will be null
for reference types like string unless you assign a different default value in the constructor, as per the other answers.
Also, by specifying different default values
public string Type { get; set; } = ""
public string Username { get; set; } = "";
public string Key { get; set; } = "";
is equivalent to assigning these values in a default constructor, i.e.
public Request()
{
Type = "";
UserName = "";
Key = "";
}
As you can imagine, this is a bit wasteful if you then immediately change the value again using object initializer syntax.
As an alternative, and if you don't require a mutable class, I would suggest instead that you provide one or more constructor overloads, which then supply suitable non-null default values for any missing fields, and then make the properties immutable e.g.
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; }
}
You can now instantiate the class without ever going through a state where any of the properties are ever null, and without the overhead of the intermediate default assignment, e.g.
var myRequest = new Request(key: "SomeKey"); // <-- Username and Type are defaulted to ""