Is constructor the only way to initialize non-nullable properties in a class in C#?

Initialise them in the definition

public string Type { get; set; } = ""
public string Username { get; set; } = "";
public string Key { get; set; } = "";

The object initializer syntax "new Request { }" is just syntactic sugar for new then assignment, so don't think you can get that to error in this case


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";     // <-- Type 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 ""