Skip to content

10.0

C# 10.0, released with .NET 6 in November 2021, introduced several features and improvements aimed at simplifying code, enhancing the clarity of programs, and reducing boilerplate code. Here are some of the key features introduced in C# 10.0, along with examples and comparisons to earlier versions of C#:

1. Global Using Directives

C# 10.0 introduced global using directives, allowing you to specify using directives that are applied globally across all source files in a project, reducing the need to include common using directives in every file.

C# 10.0 In a GlobalUsings.cs file:

global using System;
global using System.Collections.Generic;
These using directives do not need to be repeated in other source files.

C# < 10.0 Previously, you had to include common using directives in every source file, which could lead to repetitive boilerplate code at the top of each file.

using System;
using System.Collections.Generic;
// This needed to be repeated in each source file.

2. File-scoped Namespaces

C# 10.0 allows for file-scoped namespaces, reducing the indentation level for the entire file and making the code more concise.

C# 10.0

namespace MyApplication;

class MyClass
{
    // Class implementation
}

C# < 10.0 In earlier versions, namespaces required braces, which introduced an additional level of indentation.

namespace MyApplication
{
    class MyClass
    {
        // Class implementation
    }
}

3. Record Structs

C# 10.0 introduced record structs, expanding the record types introduced in C# 9.0 to struct types, providing value semantics for immutable data models.

C# 10.0

public record struct Point(double X, double Y);

C# < 10.0 Before C# 10.0, records were limited to reference types, and creating immutable value types required more boilerplate code.

public struct Point
{
    public double X { get; init; }
    public double Y { get; init; }

    public Point(double x, double y) => (X, Y) = (x, y);
}

4. Improved Interpolated Strings

C# 10.0 improved the performance and usability of interpolated strings by allowing them to be used as constants, parameters for attributes, and in more contexts where string literals are permitted.

C# 10.0

const string Name = "World";
const string Greeting = $"Hello, {Name}!";

C# < 10.0 Previously, interpolated strings could not be used in contexts that required constant expressions.

const string Name = "World";
// The following was not possible; had to use string concatenation or similar
// const string Greeting = $"Hello, {Name}!";
const string Greeting = "Hello, " + Name + "!";

5. Lambda Improvements

C# 10.0 introduced several improvements to lambda expressions, including natural type inference, making it easier to work with lambda expressions in generic contexts.

C# 10.0

var numbers = new List<int> { 1, 2, 3, 4 };
var doubledNumbers = numbers.Select(static number => number * 2);

C# < 10.0 In previous versions, it was sometimes necessary to explicitly specify the lambda parameter type, especially in generic contexts.

var numbers = new List<int> { 1, 2, 3, 4 };
var doubledNumbers = numbers.Select((int number) => number * 2);