What’s new in C# 9.0
- Top 5 new CSharp 9 features released on Nov 10 2020
- Require .NET 5 Framework and Visual Studio version 16.8.1 to use these new c#9.0 features and the sample application
C# 9.0 adds the following features and enhancements to the C# language.
Top-level programs
Top-level statements remove unnecessary ceremony from many applications like console applications.
//These 12 line of code
using System;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(“Hello World!”);
}
}
}
Now all the boilerplate code is not needed. Below 2 lines replace 12 lines of above boilerplate code.
//To these 2 line of code
using System;
Console.WriteLine(“Hello World! — I am Top Level Program”);
Init-only properties
Starting with C# 9.0, you can create init
accessors instead of set
accessors for properties and indexers. Init-only properties are great if you want to make individual properties immutable
class InitOnlyProps
{
public string Name { get; init; }public string Address { get; set; }
public InitOnlyProps()
{
Name = “anonymous”;
Address = “none”;
}public InitOnlyProps(string newName, string newAddress)
{
Name = newName;
Address = newAddress;
}private void ChangeName(string newName, string newAddress)
{
//Not allowed
//Name = newName;
Address = newAddress;
}}
InitOnlyProps props1 = new InitOnlyProps();
props1.Address= “”;
//*****Not allowed*****
//props.Name=”John”//Allowed
InitOnlyProps props2 = new InitOnlyProps { Name = “John”, Address = “USA” };//Allowed
InitOnlyProps props3 = new InitOnlyProps (“John”, “USA” );
Target-typed new
expressions
In C# 9.0, you can omit the type in a new
expression when the created object's type is already known
InitOnlyProps shorthandinstantiation = new(“John”, “USA”);
Improved pattern matching
Pattern matching(feature of C#8.0) is achieved by using the switch
operator
Several new kinds of patterns have been added in C# 9.0
Relational pattern matching in switch expression
>, <, >=, <=
Logical pattern(range) matching in switch expression
and, or, not
foreach (var temp in summary)
{
/* Not super cool code below
if (temp.Temp < 0)
{
temp.Summary = “Super Cold”;
}
else if (temp.Temp > 50)
{
temp.Summary = “Super Hot”;
}
else if (temp.Temp > 30 && temp.Temp <50)
{
temp.Summary = “Hot”;
}
else
{
temp.Summary = “I can live with it”;
}
*///New pattern matching code
temp.Summary = temp.Temp switch
{
< 0 => “Super Cold”,
> 50 => “Super Hot”,
> 30 and < 50 => “Hot”,
_ => “I can live with it”
};}
Records
Record types make it easy to create immutable reference types in .NET. Historically, .NET types are largely classified as reference types (including classes and anonymous types) and value types (including structs and tuples). While immutable value types are recommended, mutable value types don’t often introduce errors. Value type variables hold the values so changes are made to a copy of the original data when value types are passed to methods.
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:
//similar to class with some caveats
//Immutable
//ToString implementation is different
//Equals would give diff results for record and class
IdRecords id1 = new (“Parag”, “USA”);
//Not allowed
//id1.Address = “1233”;Console.ForegroundColor = ConsoleColor.DarkMagenta;
IdRecords id2 = new(“Parag”, “USA”);
InitOnlyProps classid1 = new InitOnlyProps(“Parag”, “USA”);
InitOnlyProps classid2 = new InitOnlyProps(“Parag”, “USA”);
Console.WriteLine($”ToString record — {id1.ToString()}”);
Console.WriteLine($”ToString class — {classid1.ToString()}”);
Console.WriteLine($”Equals record — {id1.Equals(id2)}”);
Console.WriteLine($”Equals class — {classid1.Equals(classid2)}”);
Sample code to explore important new c#9.0 features can be found on github(link below).