With the upcoming release of .NET 5 — the release which unifies the .NET runtimes — Microsoft recently announced the features that will be included in C## 9. With the final Preview version of C## 9 being announced today, it’s not far off.

In this article, we’ll take a look at the new features in C## 9, and how they can be used to improve your code. We’ll focus on the major features first, and discuss some of the smaller companion features towards the end. If you want to dive deeper, take a look at the Language Feature Status document in the Roslyn repository!

1. Records

Records bridge the gap that currently exists between class and struct types. Classes are more efficient to pass around, but their equality is determined by their underlying reference, rather than the values of its members. Structs get value semantics when determining equality, but have to be copied when passed around.

Because in most applications objects tend to get passed around, this effectively means that you more often than not end up implementing a class and overriding the default equality behaviour, even though value semantics would be desirable.

Records alleviate this discomfort by having value semantics, while still being passed by reference.

Classes that behave as a record are denoted by the record keyword in the type definition:

public record Order
	{
	    public int Id { get; init set; }
	    public string Status { get; init set; }
	    public bool IsPaid { get; init set; }
	}

One of the key differences between regular classes and records is that records are intended to be immutable; their state never changes. Therefore, each records represents the state of an object at a specific point in time.

Whenever the object’s state changes, we create a copy of the record, updating the members that have changed, rather than changing the original record directly. We’ll explore how records are updated in the next section.

Updating Records

Records are intended to be immutable. Instead of mutating their data, you create a new instance, but with different values. This is where the with expression comes in.

For example, consider we have an Order record whose status changes to “Delivered”, instead of updating the Status property of our order object, we’d create a new instance of the Order type, copying the values from our original order, but updating the status:

var updatedOrder = order with { Status = "Delivered" };

Unlike with var updatedOrder = order with { Status = “Delivered” }; regular reference types, the status of the order object isn’t changed, only that of the newly created updatedOrder — any code operating on the order object will still observe its previous value.

That way, each record represents an object’s state at a specific point in time. Whenever a value changes, a new record is created. This immutability allows methods that operate on a record to have the guarantee that the data it operates on will never change mid-execution.

#software-development #dotnet #c# #csharp #csharp 9 #programming-c

An Introduction to the New Features in C# 9
3.10 GEEK