In past five years, Microsoft had made a rapid enhancements in C# by introducing a plenty major features with every new version, As planed, C# 9.0 will be officially released with .NET 5 on November 2020. So we will dive into C# 9.0 new features that released on 20 may 2020 as a Preview.
1- Top-level programs
Presently, in C# coding a simple program requires a noticeable amount as initial code as following :
using System;
class Program
{
    static void Main()
    {
        Console.WriteLine("Hello World!");
    }
}
C# 9.0 introduces 
Top-level programsusingusing System;
Console.WriteLine("Hello World!");
2- Target-typed new
 expressions
new
new// Instantiation of point object
Point point = new Point(3, 5);
// Instantiation of dictionary object
Dictionary<string, List<int>> field = new Dictionary<string, List<int>>() {
    { "item1", new List<int>() { 1, 2, 3 } }
};
// implicitly typed array
var items = new[] { 10, 20, 30 };
// Instantiation of anonymous types
var example = new { Greeting = "Hello", Name = "World" };
In C# 9.0 the type is optional if there’s a clear target type that the expressions is being assigned to as following:
// initialization without duplicating the type.
Point point = new(3, 5);
Dictionary<string, List<int>> field = new() {
    { "item1", new() { 1, 2, 3 } }
};
// the type can be inferred from usage.
XmlReader.Create(reader, new() { IgnoreWhitespace = true });
3- Pattern Matching Improvements
C# 7 introduced basic pattern matching features then, C# 8 extended it with new expressions and patterns. By the time, C# 9.0 introduced new pattern enhancements as following:
declaring default identifier for type matching not required
// Before
vehicle switch
{
    Car { Passengers: 0}  => 2.00m + 0.50m,
    Car { Passengers: 1 } => 2.0m,
    Car { Passengers: 2}  => 2.0m - 0.50m,
    Car _                 => 2.00m - 1.0m,
};
// C# 9.0
vehicle switch
{
    Car { Passengers: 0}  => 2.00m + 0.50m,
    Car { Passengers: 1 } => 2.0m,
    Car { Passengers: 2}  => 2.0m - 0.50m,
    // no identifier for default type matching
    Car                   => 2.00m - 1.0m,
};
Relational patterns
C# 9.0 introduces supporting the relational operators 
<<=>>=public static LifeStage LifeStageAtAge(int age) => age switch
{
   < 0 =>  LiftStage.Prenatal,
   < 2 =>  LifeStage.Infant,
   < 4 =>  LifeStage.Toddler,
   < 6 =>  LifeStage.EarlyChild,
   < 12 => LifeStage.MiddleChild,
   < 20 => LifeStage.Adolescent,
   < 40 => LifeStage.EarlyAdult,
   < 65 => LifeStage.MiddleAdult,
      _ => LifeStage.LateAdult,
};
Logical patterns
C# 9.0 introduces supporting the logical operators 
andornotpublic static LifeStage LifeStageAtAge(int age) => age switch
{
   <2            =>  LiftStage.Infant,
   >= 2 and <12  =>  LifeStage.Child,
   >= 12 and <18 => LifeStage.Teenager,
   >= 18         => LifeStage.Adult,
};
bool IsValidPercentage(object x) => x is
    >= 0  and <= 100  or    // integer tests
    >= 0F and <= 100F or  // float tests
    >= 0D and <= 100D;    // double tests
Also 
not// before
if (!(e is null)) { ... }
// C# 9.0
if (e is not null) { ... }
4- Covariant return types
By introducing 
covariant return typesclass Compilation ...
{
    virtual Compilation CreateWithOptions(Options options)...
}
class CSharpCompilation : Compilation
{
    override CSharpCompilation CreateWithOptions(Options options)...
}
5- Extending Partial Methods
C# has limited support for developers splitting methods into declarations and definitions/implementations.
Partial methods have several restrictions:
- Must have a 
 return type.void
- Cannot have 
 orref
 parameters.out
- Cannot have any accessibility (implicitly 
 ).private
One behavior of 
partialpartialpartial class D
{
    partial void M(string message);
    void Example()
    {
        M(GetIt()); // Call to M and GetIt erased at compile time
    }
    string GetIt() => "Hello World";
}
C# 9.0 extends 
partialpartial- allow them have 
 orref
 .out
- allow 
 return typesnon-void
- allow any type of accessibility (
 ,private
 , etc ..).public
Such partial declarations would then have the added requirement that a definition must exist. That means the language does not have to consider the impact of erasing the call sites.
When a 
partialprivatepartial class C
{
    // Okay because no definition is required here
    partial void M1();
    // Okay because M2 has a definition
    private partial void M2();
    // Error: partial method M3 must have a definition
    private partial void M3();
}
partial class C
{
    private partial void M2() { }
}
Further the language will remove all restrictions on what can appear on a partial method which has an explicit accessibility. Such declarations can contain 
non-voidrefoutexternpartial class D
{
    // Okay
    internal partial bool TryParse(string s, out int i); 
}
partial class D
{
    internal partial bool TryParse(string s, out int i) { ... }
}
6- Init-only properties
In C#, it is not possible to initialize immutable properties of a class by 
Object initialize// immutable properties 
public class Person
{
    public string FirstName { get; }
    public string LastName { get;}
}
// can't be initialized using Object initialize 
// var person = new Person
// {
//    FirstName = "Ahmed",
//   LastName = "Yousif"
// }
on the other, hand if we want to initialize them using 
Object initialize // mutable properties 
public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}
...
var person = new Person
{
    FirstName = "Ahmed",
    LastName = "Yousif"
}
// property can be changed
person.FirstName = "Mohamed"
By introducing 
Init-only properties C# 9.0 introduces an 
initpublic class Person
{
    public string FirstName { get; init; }
    public string LastName { get; init; }
}
...
var person = new Person
{
    FirstName = "Ahmed",
    LastName = "Yousif"
}
// manipulating property after initialization won't be allowed
// person.LastName = "Mohamed"
7- Records
Init-only propertiesRecorddataclass public data class Person
{
    public string FirstName { get; init; }
    public string LastName { get; init; }
}
So, in this case we immuted the whole object which, consider as declaring a record state. records can be shorthand the declaration as following:
// exactly the same declaration before
public data class Person { string FirstName; string LastName; }
If you want to add a private field,you must add 
privateprivate string firstName;
8- With-expressions
Now, if we want to change the state of immutable object how we can do it! in this case we have to copy the exist object with updated values to represent a new state. by introducing 
With-expressionsvar person = new Person
{
    FirstName = "Ahmed",
    LastName = "Yousif"
}
// copy person object with update LastName
var anotherPerson = person with { LastName = "Ali" }; 
With-expressions 9- Value-based equality
Value-based equalityRecordStructsObject.Equals(object, object) Object.ReferenceEquals(object, object)var person = new Person
{
    FirstName = "Ahmed",
    LastName = "Yousif"
}
// copy person object and with same lastname
var anotherPerson = person with { LastName = "Yousif" }; 
// they have the same values so will be true
// Equals(person, anotherPerson)
// they aren’t the same object so will be false
// ReferenceEquals(person, anotherPerson)
 
10- Positional records
Let's say we want to apply positional approach to a record class 
to get benefits of positional deconstruction so, in this case you have to explicitly implement constructor and deconstructor of the record as following:
public data class Person 
{ 
    string FirstName; 
    string LastName; 
    public Person(string firstName, string lastName) 
      => (FirstName, LastName) = (firstName, lastName);
    public void Deconstruct(out string firstName, out string lastName) 
      => (firstName, lastName) = (FirstName, LastName);
}
But there's a good news by introducing C# 9.0 there is a shorthand expressing exactly the same thing.
// equivalent to previous one 
public data class Person(string FirstName, string LastName);
now you can deconstructing your object as following:
var person = new Person("Ahmed", "Yousif"); // positional construction
var (fName, lName) = person;              // positional deconstruction
And much more features…
So, the best place to check out the last updates of upcoming features for C# 9.0 is the Language Feature Status on the C# compiler Github repo.
