In this article, we are going to learn how to initialize the parameters of a record type in C#. For an overview of what records are, have a look at this article.
So, let’s dive in.
How to Initialize Parameters of a Record
Let’s assume we declare a simple record with two parameters. We use the constructor to set the value of the parameters:
public record Person { public string FirstName { get; set; } public string LastName { get; set; } public Person(string firstName, string lastName) { FirstName = firstName; LastName = lastName; } }
The syntax to declare the record is very similar to how we would declare a class but uses the record
keyword instead of class
. To initialize the parameters of the Person
record, the syntax is also similar to initializing those in a class:
var person = new Person("Joe", "Bloggs");
How to Initialize Parameters of a Record Using Positional Parameters
In the previous example, the properties of the record were mutable. One of the reasons to use records is that their properties can be immutable using the init
keyword. This means we can only set the value of a property during construction:
publicĀ stringĀ FirstNameĀ {Ā get;Ā init;Ā } public string LastName { get; init; }
Alternatively, we can achieve the same with a single line of code using the primary constructor:
public record Person(string FirstName, string LastName);
When we use a primary constructor with a record that has parameters, the compiler creates an immutable backing public property for each of our parameters. We call these parameters positional parameters.
It might look slightly unusual that the parameters have Pascal case, not Camel case. This is intentional though, since the compiler will use the exact case of the parameters to generate the backing properties. So if we want to maintain Pascal case properties, we need to use Pascal case parameters.
To instantiate the record, we use the same syntax:
var person = new Person("Joe", "Bloggs");
A More Advanced Example With a Default Value
Now, let’s see what happens if we add an optional parameter called friends to our Person
record:
public record Person { public string FirstName { get; set; } public string LastName { get; set; } public IEnumerable<string> Friends { get; set; } public Person(string firstName, string lastName, IEnumerable<string>? friends = null) { FirstName = firstName; LastName = lastName; Friends = friends ?? new List<string>(); } }
In this case, if the person has some friends, we can pass this into the constructor when instantiating the record:
var person = new Person("Joe", "Bloggs", new List<string> { "Alice", "Bob"});
We set the Friends
property in our constructor. If the person has no associated friends, we can either pass a null
into the constructor or omit it completely since it is an optional parameter. In this case, the Friends
property is set to an empty list in the constructor.
However, again there is a much more concise way of declaring our record type using a primary constructor:
public record Person(string FirstName, string LastName, IEnumerable<string>? Friends = null) { public IEnumerable<string> Friends { get; init; } = Friends ?? new List<string>(); };
The FirstName
and LastName
properties are generated by the compiler as we saw before. With the Friends
parameter, the compiler would normally create a backing property for us, with the default value of null
, not an empty list.
Instead, we can create the property ourselves and ensure it is set to an empty list if Friends
is null
. We also make it immutable by using the init
keyword.
Conclusion
We initialize parameters for a record
type in a similar way to how we initialize parameters for classes.
We have also seen that the compiler automatically creates properties when we use a primary constructor with records which can simplify our code. Finally, we have seen how we set a default value for a property in a more complicated case.