C# 9.0 Preview
New Features
Tags: csharp, dotnet
Published: 2020-06-05 18:52:47

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/smqibv5n1mlca45s6gxc.png)
# C# 9.0 New Features

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.
<br />
## 1- Top-level programs

Presently, in C# coding a simple program requires a noticeable amount as initial code as following :

<br />

```cs
using System;
class Program
{
    static void Main()
    {
        Console.WriteLine("Hello World!");
    }
}
```

C# 9.0 introduces `Top-level programs` feature that, allows you to code your main program (Any statement is allowed) at the top level instead immediately after `using` statements and no need to declare any namespace, class or main method.As per C#, you must have only one entry point for your program so, you can exclusively do this in only one file as following:
```cs
using System;

Console.WriteLine("Hello World!");
```

<br />
<br />

## 2- Target-typed `new` expressions

`new` expressions always required a type to be specified (except for implicitly typed array or anonymous types) as following. 

```cs
// 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:

```cs
// 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 });

```
<br />
<br />
## 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

```cs
// 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,
};
```

```cs
// 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 `<`, `<=`, `>`, and `>=` patterns as following:

```cs 
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 `and`, `or`, and `not` patterns as following:

```cs 
public 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` is going to be convenient in if-conditions containing is-expressions where, instead of unwieldy double parentheses.

```cs
if (!(e is null)) { ... }

if (e is not null) { ... }
```
<br />
<br />
## 4- Covariant return types

By introducing `covariant return types` feature in C# 9.0, you are permitted to override a method or a read-only property to return a more derived return type than the method or property overridden as following:

```cs
class Compilation ...
{
    virtual Compilation CreateWithOptions(Options options)...
}

class CSharpCompilation : Compilation
{
    override CSharpCompilation CreateWithOptions(Options options)...
}
```
<br />
<br />
## 5- Extending Partial Methods

C# has limited support for developers splitting methods into declarations and definitions/implementations.

Partial methods have several restrictions:
1- Must have a void return type.
2- Cannot have ref or out parameters.
3- Cannot have any accessibility (implicitly private).

One behavior of partial methods is that when the definition is absent then the language will simply erase any calls to the partial method .

```cs
partial 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 `partial` methods to remove most of the existing restrictions around `partial` methods as following:

1-allow them have `ref` or `out`.
2-allow `non-void` return types
3-allow any type of accessibility (`private`, `public`, etc ..). 

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 partial method has an explicit accessibility modifier though the language will require that the declaration has a matching definition even when the accessibility is private:

```cs
partial 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-void` return types, `ref` or `out` parameters, `extern` modifier, etc... These signatures will have the full expressivity of the C# language.

```cs
partial class D
{
    // Okay
    internal partial bool TryParse(string s, out int i); 
}

partial class D
{
    internal partial bool TryParse(string s, out int i) { ... }
}
```
<br />
<br />
## 6- Init-only properties

In C#, it is not possible to initialize immutable properties of a class by `Object initialize` as following.

```cs
// 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` we have to make these properties mutable that, open the door for manipulating it as following: 

```cs
// 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 solve that hard equation! 
C# 9.0 introduces an `init` accessor that allow initializing property only during object initialization as following:

```cs
public 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"

```
<br />
<br />
## 7- Records
`Init-only properties` is a great feature for making individual properties immutable.But what if we want to make the whole object immutable, Here we can highlight the importance of introducing `Record` feature. by using `data` keyword before `class` keyword as following:

```cs
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:

```cs
// exactly the same declaration before
public data class Person { string FirstName; string LastName; }
```
If you want to add a private field,you must add `private` modifier explicitly:

```cs
private string firstName;
```
<br />
<br />
## 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-expressions` feature we can achieve it so easy as following:

```cs
var person = new Person
{
    FirstName = "Ahmed",
    LastName = "Yousif"
}

// copy person object with update LastName
var anotherPerson = person with { LastName = "Ali" }; 
 
```
`With-expressions` feature uses object initializer syntax to set state what’s different in the new object.
<br />
<br />
## 9- `Value-based equality`

`Value-based equality` feature allows you to compare two instances of `Record` Class value base equality same as `Structs` by comparing all properties in the object using `Object.Equals(object, object)` static method. on the other hand if you want check reference base equality you can use `Object.ReferenceEquals(object, object)` static method as following:

```cs
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)
 
```
<br />
<br />
## 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:

```cs
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.

```cs
// equivalent to previous one 
public data class Person(string FirstName, string LastName);


```
now you can deconstructing your object as following:

```cs
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 last updates of upcoming features for C# 9.0 is the [Language Feature Status](https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md
) on the C# compiler Github repo.