What’s New in C# 9.0

What’s New in C# 9.0

While C# 9 is taking its shape before it gets officially gets into Developer’s hands. Let’s take a glance at what are the new features in C#9.
With every version of C#, we see the strive for greater clarity simplicity in common coding scenarios, and C# is no different from that. This time the focus is more on the terse and immutable representation of data shapes.

Let’s take a look at the features now here:

Init-only Properties
Object initializers are pretty awesome. They give the client of a type a very flexible and readable format for creating an object, and they are especially great for nested object creation where a whole tree of objects is created in one go. Here’s a simple one:

Ex :
public class Person
{
public string FirstName { get; init; }
public string LastName { get; init; }
}

Init Accessors and read-only fields
Because init accessors can only be called during initialization, they are allowed to mutate read-only fields of the enclosing class, just like you can in a constructor.

Records
Init-only properties are great if you want to make individual properties immutable. If you want the whole object to be immutable and behave like a value, then you should consider declaring it as a record:
public data class Person
{
public string FirstName { get; init; }
public string LastName { get; init; }
}
The data keyword on the class declaration marks it as a record.

With-Expressions
When working with immutable data, a common pattern is to create new values from existing ones to represent a new state. With-expressions use object initializer syntax to state what’s different in the new object from the old object. You can specify multiple properties. The with expression causes the copy constructor to get called and then applies the object initializer on top to change the properties accordingly.

Data Members
Records are overwhelmingly intended to be immutable, with init-only public properties that can be non-destructively modified through with-expressions. To optimize for that common case, records, change the defaults of what a simple member declaration of the form string FirstName means. Instead of an implicitly private field, as in other class and struct declarations, in records, this is taken to be shorthand for a public, init-only auto-property! Thus, the declaration:

public data class Person { string FirstName; string LastName; }

Positional Records
Sometimes it’s useful to have a more positional approach to a record, where its contents are given via constructor arguments and can be extracted with positional deconstruction.

It’s perfectly possible to specify your constructor and deconstructor in a record:

Value-based equality and inheritance
Similarly to the with-expression support, value-based equality also has to be “virtual”, in the sense that Students need to compare all the Student fields, even if the statically known type at the point of comparison is a base type like Person. That is easily achieved by overriding the already virtual Equals method.

However, there is an additional challenge with equality: What if you compare two different kinds of Person? We can’t just let one of them decide which equality to apply: Equality is supposed to be symmetric, so the result should be the same regardless of which of the two objects come first. In other words, they have to agree on the equality being applied!

An example to illustrate the problem:
Person person1 = new Person { FirstName = “Scott”, LastName = “Hunter” };
Person person2 = new Student { FirstName = “Scott”, LastName = “Hunter”, ID = GetNewId() };

Are the two objects equal to one another? person1 might think so since person2 has all the Person things right, but person2 would beg to differ! We need to make sure that they both agree that they are different objects.

Once again, C# takes care of this for you automatically. The way it’s done is that records have a virtual protected property called EqualityContract. Every derived record overrides it, and to compare equal, the two objects must have the same EqualityContract.