C#9 Records Appreciation Post
record
s are a new construct in C# 9. The idea comes from known working features from other languages. The promise of
immutability and limiting “Spooky side effects at a distance” has me interested in replacing classes with Records!
So what is a record
vs a class
?
A record
IS a class
, with syntactic sugar on top. The record is more similar to a struct
in practice, but
it has the advantages of classes with regards to garbage collections and speed.
Why should I use records then? I already have “init” properties etc.
1. Records are Immutable (Unchangeable)
var nils = new MyRecord(Name: "Nils")
nils.name = "Not Nils" // <- This cannot happen.
// But we can create a new Nils
var newNils = nils with { name: "New Nils" }
You might think that this sounds like a hassle. But we are back to the spooky side effects to explain why its cool.
When I pass “nils” here to a method sendToVacation(nils)
I can be certain that nils do not change, if the return type of sendToVacation is not a MyRecord
.
2. Less Code for common stuff
You might say that I could do most of this before with classes and constructors.
public record MyRecord {
public string Name { get; init; }
}
public class MyClass {
public string Name { get; init; }
}
The MyRecord
and MyClass
above here might seem identical, but under the hood there are some changes already.
Records have built in
- value equality (No more IEquatable!)
- formatting for display (no more “.ToString()” -> Object in console)
- syntax for nondestructive mutation.
- You can copy a Record without any manual boilerplate.
3. Concise Syntax
The magic here is the “oneliner” to create records.
public record MyRecord(string Name); // Thats it
It even supports inheritance as a oneliner!
public record BaseRecord(int Id);
public record MyRecord(int Id, string Name) : BaseRecord(Id);
Attributes are also supported, so all backing fields have the same control as before
public record BaseRecord([property: JsonName("_id")] int Id);
public record MyRecord(int Id, [property: JsonName("name")] string Name) : BaseRecord(Id);
And I can extend the record with my own methods.
public record MyRecord(string Name){
public int CalculateNumCharsInName(){
return Name.length
}
};
Cool!
There is much more to know about records, but this was a quick demonstration. Other advantages include great nullable
support, but that will be in a later blog.
Thats all for this time.
Code Snippets are licensed under MIT No Attribution