Microsoft is plowing ahead with the development of C# 9.0, an upgrade to the company’s type-safe, object-oriented language that will include new capabilities such as records and value-based equality.
The new features in C# 9.0, detailed at Build by C# lead designer Mads Torgersen, include records, for declaring a whole object to be immutable and have it behave like a value. Records are intended to be seen more like data and less like objects.
This is in addition to
with expressions, which use object initialiser syntax to show what is different in a new object compared to an old one, alongside improved pattern matching and value-based equality.
All objects inherit a virtual
Equals(object) method from the
object class. This serves as a basis for the
Object.Equals(object, object) static method when both parameters are non-null.
Structs override this to have “value-based equality,” allowing comparisons of each field of the struct by calling
Equals on them in a recursive manner. Records also do this. Thus, in accordance with “value-ness,” two record objects can be equal without being the same object.
Other key features include relational patterns, which are patterns corresponding to relational operators
<=, and so on, as well as logical patterns, which combine patterns with logical operators
not, spelled out as words to avoid confusion with operators used in expressions.
Simple type patterns are also available, alongside init-only properties, introducing an i
nit assessor that is a variant of the
set assessor, for calling during object initialisation. These properties address a limitation of object initialisers, in which properties must be mutable for these initialisers to work.
As outlined by Torgersen, improved target typing is on the table as well, which is a term describing when an expression gets its type from the context where it is being used. For example,
null and lambda expressions are always targeted. With C# 9.0, some expressions that were not previously target-typed now can be guided by their context.
new expressions, in which the type can be left out if there is a clear type that the expression is being assigned to, have been included, backed by covariant returns to express that a method override in a derived class has a more specific return type than the declaration in the base type.
Rounding off the new features are positional records - providing an approach to records where contents are given via constructor arguments and can be extracted with positional deconstruction - and top-level programs to address the issue of too much boilerplate code.