Top 10 C# 9.0 Features to Make Your Codes Simpler | Desuvit

Microsoft is impressively thriving with the evolution of C# 9.0, an advancement to the corporation’s type-safe and object-oriented language, which now encompasses new capabilities like records, value-based equality, and more.
C# 9.0 is incorporated with several new features and stresses on a few themes. C# 9.0 is a part of .NET 5, which moves toward the journey of a single .NET ecosystem.

The new features lay stress on modern workloads, i.e., the software applications and even the services you are currently building. The C# 9.0 compiler arrives along with the .NET 5.0 SDK. Various C# 9.0 features depend upon the fresh features in the .NET 5.0 libraries and upgrades to the .NET CLR that are part of .NET 5.0. Hence, C# 9.0 is supported solely on .NET 5.0.

Some Important Features

Here are 10 crucial features of Microsoft’s C# 9.0 that make it easy and interesting to work with.

1. Record Types

C# 9.0 has introduced record types. One can utilize the record keyword for defining the reference type, which will offer an inbuilt functionality to encapsulate the data. Record types having immutable properties can also be created with the help of positional parameters and basic property syntax.
Record types having mutable fields and properties can also be created. One must remember that record types have the primary intention to support immutable data. Record types offer useful features like concise syntax for indestructible mutation, value equality, inbuilt formatting display, and assistance in inheritance hierarchies.

Below is a sample code showing the usage of record type.

public class Customer
    {
        public string LastName { get; }
        public string FirstName { get; }
        public Customer(string first, string last) =>;(FirstName, LastName) = (first, last);

    }

2. Init Only Setters

Init only setters offer a continuous syntax for initializing an object’s members. Property initializers make it quite clear about different values which are setting different properties.
Beginning with C# 9.0, init accessor can be created rather than a set assessor for indexes and properties. Callers can utilize property initializer syntax for the setting of the values in creative expressions, but these types of properties are read-only once the construction is completed.
Init only setters offer a window to amend state. That window shuts down after the construction phase. After all the initialization, the construction phase effectively terminates; also, the property initializers and with-expressions have finished.

Below is a sample code of Init only setters.

public class Friend
    {
        public Friend(string firstName, string lastName)
        {
            FirstName = firstName;
            LastName = lastName;
        }

        public string FirstName { get; init; }
        public string LastName { get; init; }

    }

3. Top-Level Statements

Top-level statements eliminate nonessential ceremonies from various applications. With the help of top-level statements, one can replace all of that boilerplate by the ‘using’ directive also the single line which does all the work.
Only one file from the applications can utilize top-level statements. If the compiler finds out that top-level statements are being used in multiple files, it will be an error. Another common error is, if you integrate top-level statements along with a declared program entry point mode, generally the Main method. You may think of one file containing all of the statements found in a Program Class’s Main method.

With the top level statement, instead of writing the below code,

using System;

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

You can write as,

using System;
Console.WriteLine("Hello World!!!");  

4. Pattern Matching Enhancements

  • C# 9 contains fresh new pattern matching improvements. Some of them are as follows:
  • Type patterns match a variable is a kind
  • Parenthesized patterns emphasize or stress the precedence of combinations of patterns
  • Conjunctive and patterns need both the patterns for the match
  • Disjunctive or patterns need anyone patterns for matching
  • Negated not patterns need that a pattern does not match
  • Relational patterns need the input to be lesser, greater, or greater than, or equal less than or equal to the given
  • These patterns enhance the syntax for patterns

5. Covariant Return Types

Covariant return types are a new feature of the C# 9.0 that lets you specify the return types on the overridden methods. The override method will return types derived from overridden bases. This is useful for records, virtual clones, or factory methods. You can observe the use of covariant return types here.

6. Improved Target Typing

Many of the other features assist you in writing code faster.
When the type of the generated object is already known, you can omit the type in a new expression in C# 9.0. Field declarations are the most typical application. The most common use is in field declarations as expressed below.

private List <WeatherObservation> _observations = new();

When you need to construct a new object to send as a parameter to a method, you can use target-typed new. The term “target typing” refers to when an expression’s type is defined by the context in which it is employed.
Null and lambda expressions, for example, always target types.
Some expressions like conditional expressions and more that weren’t previously target typed can now be guided by their context in C# 9.0.

7. Performance And Interop

Three new features enhance the support for low-level libraries and native interop that need high performance: function pointers, native-sized integers, and eliminating the localsinit.

  • Native Sized integers – These are nint and nuint. IntPtr and UlntPtr are the underlying systems that help express the native integers. Native sized integers increase integer math performance.
  • Function Pointers – Lets you access IL opcodes ldftn and calli. Plus, you can declare function pointers using the delegate syntax.
  • Eliminate the localsinit – You can use the System.Runtime.CompilerServices.SkipLocalsInitAttribute to ensure the compiler doesn’t emit the localsinit flag. You add this SkipLocalIsInitAttribute to a single method, property, class, struct, module, or interface.

All these performance and Interop features enhance performance in some scenarios. You must ensure you test the native integer code on multiple target platforms with different sized integers. For the other two codes use Unsafe Code and Pointer Types.

8. Apply Attributes to Local Functions

Apply attributes to local functions which are nested methods inside a containing member. For example, you can apply nullable attribute annotations to local functions and get the null status of the containing members.

Another example, you can add a conditional attribute to your local function. Just ensure the local condition is static and the return type is void.
This feature helps to make the code cleaner and it’s quite useful. Here’s another example of using an attribute to a local function.

using System;
using System.Diagnostics;

namespace CSharpDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            [Conditional("DEBUG")]
            static void DoAction()
            {
                //Perform Action
            }

            DoAction();
        }
    }
}

9. Support For Code Generators

C# code generators are a component comparable to a Roslyn analyzer or code repair that you can develop. Code generator is a piece of code that gets run during the compilation process. This can inspect your program and produce additional files which are compiled together with the rest of the code.
A typical code generator looks for attributes or other conventions in the code. Source code generators can be visualized as below.

Source code generators

Source: Microsoft

10. Foreach Loop

Foreach Loops are iteration statements that enumerate the elements of a collection and it executes the body for each element of its collection. The C# 9.0 upgrade enables the foreach loop to recognize and use the extension method GetEnumerator to satisfy the foreach pattern.
This upgrade ensures that foreach pattern is consistent with pattern-based constructions like pattern-based deconstruction and async. So, you’ll be able to add foreach support to any type. However, add the foreach support only when you need to enumerate an object in your design.

Conclusion

Although C# 9 is relatively new, the team of language designing is already thinking of versions of C#: 10 to come and beyond. Do you want to use C# 9 for your project? Contact us now to get all the help you need!

Enjoyed this article? Subscribe for more valuable and great content !

Enter your email address below to get new articles with valuable content delivered straight to your inbox, plus special subscriber-only content to help you with your next mobile app or software development project.

By subscribing, you agree with our privacy policy and our terms of service.