C# is well on the way to his third decade of life. Originally released in 2000, the language has grown and changed across 9 major versions. Once a knock-off of Java into all, but the name leaped forward on many aspects.
Throughout its life, the discharge of a replacement version of the language has been high including releases of the latest versions of Visual Studio also like releases of the .NET runtime. This combination has in fact reduced the rate of innovation.
Proposed C# 9 Features:
1. Top-level statements
Top-level statements remove unnecessary ceremonies from many applications.
Writing a simple program to C# requires a considerable amount of boilerplate code. Consider the canonical “Hello World!” program.
With top-level statements, we can eliminate the boilerplate code and start coding the logic right away.
We might wonder how it is working without class & method signatures [namespace is optional] & how does .NET framework identifies the entry point. Well, what C# 9 does is, if we have a class file with the top-level statement, then it is assumed to be the entry point of the application. Top-level statements are great for small console programs, snippets, and utilities. It makes life simpler.
The program has to occur after the use and before any type or namespace declarations in the file, top-level statements should be available only in one file within a project, just as you can have only one Main method. If you would like to return a status code, you are welcome to do so. If you would like to await belongings you can do this. And if you would like to access command-line arguments, args is out there as a “magic” parameter.
Local functions are some form of statement and are also permitted in the top-level program. It is a mistake to call them from anywhere outside of the top-level statement section.
2. Init only setters
In this Product type, there are ProductId, ProductName, and FixedPrice with both getter and setter accessors and the concern here is the object is mutable. It means once the object is created, we can change values like below:
To make immutable this, by using a constructor we can accomplish that.
In the above code, a considerable amount of boiler code required to support it. That where the new C# 9 feature Init-only setter shines. Instead of using Set, we can use the init keyword. This makes it immutable or read-only. If we try to change when the property is initialized, it won’t allow it, the compiler will throw the error. And this is the big change, which can get rid of a lot of boilerplate code.
Records define an immutable reference type and behave like a value type. Once the record is defined, we can’t modify the values of any properties of the record instances.
To make the entire object immutable, an init keyword must be defined on each of the properties in case of implicit parameterless constructors are used.
The Members are implicitly public in records if you don’t precise it. Records introduce public init-only auto-property that is a shorthand of the previous declaration:
Records support inheritance. You may report a new record derived from the Person as below and You may also seal the records to avoid further derivation.
By default, regular classes are equal when they underlying reference. Its behavior changes if you declare your class as a record. As opposed to comparing the object reference, the records are compared by value. It means two different objects holding the same values will be considered equal and hashCode will be the same. Contents will able to define the Records, not by identity.
There is value in adopting a more positional approach to a record and its contents are given via constructor arguments and can be extracted with positional deconstruction. It is entirely possible to define your own constructor and deconstructor in a record:
But the syntax is much shorter to express precisely the same thing.
This declares the public init-only auto-properties and the constructor and the deconstructor, to let you write:
In the case of the auto property, own the same name property in place, and the generated constructor and deconstructor will just use that one.If so, the parameter is in use for initialization. Let’s say, for example, that you would prefer to see FirstName as a protected property:
A positional record may invoke a basic constructor in the following manner:
When working with immutable data, the most common task is to create a new value from an existing value to represent the new state and it is called a non — destructive mutation. Now, let’s talk about ‘With Expressions’. We can define multiple properties using the With Expression. The ‘with the expression’ calls the copy constructor to be called and then applies the object initializer at the top to change the properties accordingly. Let us observe the feature,
Now everything is fine. Suppose the student record consists of 40 properties. It is not a good idea to use the above method. Because there’s a lot of code involved. From the earlier version, using a copy constructor new object can be created using both old and new object properties in accordance with the request. Now, this can be handled a lot more efficiently using our new C# 9 function ‘with expression’ by following way we shall obtain the same result.
4. Improved pattern matching
Pattern matching was introduced in C# and has evolved significantly since then. The newest improvement was quite exciting on C#. Pattern matching lets the developer match a value (or an object) with certain patterns to pick a branch/block of the code.
C# 9 allows you to use a relational pattern which enables the utilization of <, >, <= and >= in patterns like this:
What We Currently Have
First of all, imagine a drag within the C#8 which we should always be ready to resolve with Relational Pattern Matching in C# 9 so we will actually see power.
Let’s take the following code:
How could we improve it? Well, we can still use If/Else from above in most cases only for its simplicity. But, we could use Pattern Matching which is introduced in C# 7 with a switch statement. It’ll seem like this:
Not bad, right? But we don’t really add anything to If/Else statements, in fact, we actually added even more code here. If we were to use C# 8, then we could use Switch Expressions. It would be like this:
Logical patterns && Relational Pattern Matching In Switch Statements/Expressions
C# 9 lets you use logical operators like ‘and’, ‘or’ and ‘not’, they can even be combined with relational patterns like this and We can still improve the above code like this:
5. Target-typed ‘new’ expressions
We can omit the type in the ‘new expression’ when the created object is already known.
We know that the above syntax is available from the earlier version of C#. new expressions in C# have always required a type to be specified (except for implicitly typed array expressions).In C#-9, we don’t have to mention the record type on the class name for the new expression. Let update the above code like below and we will get the same result.
The most common use of this feature is while defining the field declarations. This is often particularly nice once you have tons of repetition, like in an array or object initializer: