Record in C#
Introduction
With the release of C# 9, Microsoft introduced records. The
record keyword gives a reference type new superpowers like immutability
declared with positional records (or by using init-only properties), equality
comparisons that mimic value types, and with-expressions that allows you to
create a new record instance with the same property values, the properties you
need to change. This drastically simplifies the process to copy objects.
In this article, we will see what a record struct is, and
why a record class doesn’t behave like a record struct.
Syntax
First of all, Microsoft has made an improvement to record
classes. With C# 9, to declare a record you replaced the “class” keyword with
“record.” To avoid confusion when declaring structs as records, C# 10 allows a
new syntax to declare a class as a record by mixing record and class keywords:
public record class Naija {}
The C# 9 syntax remains valid:
public record Naija {}
Declaring a struct as a record looks like this:
public record struct Naija {}
It’s a more convenient approach to avoid confusion between a
record class and a record struct. A record struct is a struct with all its
struct properties and a record class is a class with all its class properties.
Immutability
Init-only properties are allowed on record structs:
public
record struct Product
{
public string Name { get; init; }
public int CategoryId { get; init; }
}
If you try to reassign a property that has the init keyword
set after its initialization you’ll get a compilation error:
using
System;
public class
Program
{
public static void Main()
{
var product = new Product
{
Name = "VideoGame",
CategoryId = 1
};
product.Name = ""; // Error
CS8852 Init-only property or indexer
'Product.Name' can only be assigned in an object initializer, or on 'this' or
'base' in an instance constructor or an 'init' accessor.
}
}
Using positional records is quite different for record
structs. Positional records on struct doesn’t make the record immutable as a
record class. Because it’s a struct you have to set the readonly keyword to
make the record struct immutable. The following code is equivalent to the
previous declaration above:
public
readonly record struct Product(string Name, int CategoryId);
With-expressions
Like a record class, a record struct allows the usage of
with-expressions and works similarly to a record class:
using
System;
public
class Program
{
public static void Main()
{
var product = new Product
{
Name = "VideoGame",
CategoryId = 1
};
}
Equality comparison
Because a record struct is a struct, comparing (with Equals
method) two structs that have the same values will always return true. A struct
is a value type, unlike a class. A regular struct doesn’t implement == and !=
operators, so it’s impossible to compare two structs with these operators.
However, the comparison with these operators is allowed on a record struct:
using
System;
public
class Program
{
public static void Main()
{
var product1 = new Product
{
Name = "VideoGame",
CategoryId = 1
};
var product2 = new Product
{
Name = "VideoGame",
CategoryId = 1
};
Console.WriteLine(product1.Equals(product2)); // Returns true
Console.WriteLine(product1 ==
product2); // Returns true. Only allowed on record structs, not allowed on
regular structs
}
}
Printing members
Record structs implement a new override of the ToString()
method that allows printing a structured string of the struct record. With the
same signature of Product struct, let’s compare the output:
public
class Program
{
public static void Main()
{
var product1 = new Product
{
Name = "VideoGame",
CategoryId = 1
};
Console.WriteLine(product); // Will
output: Product { Name= VideoGame, CategoryId = 1 }
}
}
Comments
Post a Comment