C# 10 Features

I’m going to talk about every single C# 10 features. We will look at them individually with an example.

The top 6 features are listed down.

  1. Global using directive
  2. File Scoped Namespace
  3. Constant Interpolated strings
  4. Lambda Improvements
  5. Null Parameter Checking

IDE which I have used for preparing the examples

  • Microsoft Visual Studio Community 2022 (64-bit)
  • Version:  17.0.5

Global using Directive

This is one of the interesting features. Let’s go ahead and create a Console application in VS 2022 and add the below lines into Program.cs file

using System.Text.Json;
var names = new[] { "Prasad", "Praveen" };
var serialized = JsonSerializer.Serialize(names);
Console.WriteLine(serialized);

This code is perfectly valid in C# 9.0.

Assume that we need to utilize the JsonSerializer.Serialize() method in multiple files under the same project, Till C# 9.0, we have only one option to add the reference System,Text.Json at the beginning of each files. In C# 10, Microsoft has been introduced a new feature to add the reference globally at one place using the keyword “global”. It is recommended to create a separate file which will contain these imports, something like “usings.cs”

C# 10 code would look like below

Program.cs

var names = new[] { "Prasad", "Praveen" };
var serialized = JsonSerializer.Serialize(names);
Console.WriteLine(serialized);

A new file usings.cs will be created and moved all the using imports into it.

Usings.cs

This class file will have only global using System.Text.Json

Assume that I’m going to comment out the line in Usings.cs, if you go back to Program.cs class, you will be getting a compiler error. To resolve this issue, we can edit the project file, and add the <ItemGroup> tags

GlobalUsingDirective.csproj( this is my project file)

<PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
</PropertyGroup>
       <ItemGroup Condition="'$(ImplicitUsings)'=='true' Or '$(ImplicitUsings)'== 'enable'">
             <Using Include="System.Text.Json"/>
       </ItemGroup>
</Project>

File Scoped Namespaces

Assume that I have a class file Employee.cs and inside the class, the code looks like below

namespace FileScopedNamespace
{
    internal class Employee
    {
        public string Name { get; set; }
    }
}

I’m going to add a new namespace within the same file as below, now my Employee.cs file looks like below since in theory, we can have multiple namespaces in a file.

namespace FileScopedNamespace
{
    internal class Employee
    {
        public string Name { get; set; }
    }
}
namespace FileScopedNamespace1
{
    internal class Employee1
    {
        public string Name { get; set; }
    }
}

In my 10 years of career in C#, I have never seen such a class file with multiple namespaces. I assume, C# Dev Team also may have same thoughts and what they did, they just removed the pointless nesting of namespace and class and converted into File Scoped Namespace as below

namespace FileScopedNamespace;
internal class Employee
{
    public string Name { get; set; }
}

Whatever we are in this Employee.cs file comes under the namespace "FileScopedNamespace;".   This is really amazing, and I love this feature.

Constant Interpolated strings

This is another feature which I really like. Assume I have a class like below, I’m trying to apply string interpolation on constant variables.

namespace ConstantInterpolatedString
{
    public static class EmailMessages
    {
        private const string Salutation = "Welcome";
        public static class Header
        {
            public const string SalutionTeamplate = Salutation + " to constant Interpolation";
        }
    }
}

This can be converted into Constant interpolation as below

namespace ConstantInterpolatedString
{
    public static class EmailMessages
    {
        private const string Salutation = "Welcome";
        public static class Header
        {
            public const string SalutionTeamplate = $"{Salutation} to Interpolation";
        }
    }
}

Before C# 10, there was no option to apply interpolation on const variables. It will throw the below compiler error

The expression being assigned to EmailMessages.Header.SalutionTemplate must be constant.

Lambda Improvements

Here we will look at some of the lambda improvements.

Previously, we had a function as below

using System;
Func<string> welcome = () => "Welcome to Lambda Improvements";
Console.WriteLine(welcome);

Here we have a func delegate which returns a string.

Note:

Ensure that our language version is pointing to 9.0 in project file as below

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
       <LangVersion>9.0</LangVersion>
  </PropertyGroup>
</Project>

Now let’s change the syntax of func delegate as below

using System;
var welcome = () => "Welcome to Lambda Improvements";
Console.WriteLine(welcome);

You will get an error as below

Feature ‘inferred delegate type’ is not available in C# 9.0. Please use language version 10.0 or greater.

Now, update the language version in project file and see.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
       <LangVersion>10.0</LangVersion>
  </PropertyGroup>
</Project>

The code will work as expected.

Next improvement,

Assume that we have the below code

using System;
//var welcome = () => "Welcome to Lambda Improvements";
var text = () => null;
//Console.WriteLine(welcome);

This will raise exception as below

The delegate type could not be inferred

There is an alternative as below

using System;
//var welcome = () => "Welcome to Lambda Improvements";
Func<string?> test  = () => null;
//Console.WriteLine(welcome);

This works fine. However, I want to rewrite this line using var. how? Please see the below syntax

using System;
//var welcome = () => "Welcome to Lambda Improvements";
var text  = string? () => null;
//Console.WriteLine(welcome);

This code will build with zero errors.

Null Parameter Checking

In C # 9.0, we can write the null check as below

string? text = null;
SayHello(text);
void SayHello(string message)
{
    if(message is null)
    {
        throw new ArgumentNullException(nameof(message));
    }
    Console.WriteLine(message);
}

In C# 10.0, we can replace the if condition with below one-liner code

string? text = null;
SayHello(text);
void SayHello(string message)
{
    //if(message is null)
    //{
    //    throw new ArgumentNullException(nameof(message));
    //}
    ArgumentNullException.ThrowIfNull(message);
    Console.WriteLine(message);
}

Thank you for reading my article. I will come up with other features in the upcoming articles. Please provide your feedback in the comment box.