Skip to content

11.0

C# 11.0, which is part of the .NET 7 release in November 2022, introduced several new features and enhancements that further improve the language's expressiveness, safety, and performance. Here are some of the key features introduced in C# 11.0, along with examples and comparisons to earlier versions of C#:

1. List Patterns

List patterns allow for concise syntax when working with lists or arrays, enabling pattern matching based on the contents of a collection.

C# 11.0

int[] numbers = { 1, 2, 3, 4, 5 };
if (numbers is [1, 2, .., 5])
{
    Console.WriteLine("Starts with 1, 2 and ends with 5");
}

C# < 11.0 Previously, achieving similar functionality required manual checking of individual elements and the collection's length, which was more verbose and error-prone.

int[] numbers = { 1, 2, 3, 4, 5 };
if (numbers.Length >= 3 && numbers[0] == 1 && numbers[1] == 2 && numbers[^1] == 5)
{
    Console.WriteLine("Starts with 1, 2 and ends with 5");
}

2. Required Members

C# 11.0 introduces the concept of required members, allowing you to specify that certain properties or fields must be initialized when an object is created, enhancing object initialization safety.

C# 11.0

public class Person
{
    public required string Name { get; set; }
}

var person = new Person { Name = "Alice" }; // Compiles fine
// var person = new Person(); // Error: The required property 'Name' must be initialized

C# < 11.0 Before C# 11.0, ensuring that properties were initialized required custom validation logic, possibly in the constructor or via a factory method.

public class Person
{
    public string Name { get; set; }

    public Person(string name)
    {
        Name = name ?? throw new ArgumentNullException(nameof(name));
    }
}

3. Raw String Literals

Raw string literals simplify the declaration of strings that contain newlines, quotes, and other special characters without the need for escape sequences, making it easier to work with JSON, XML, or HTML snippets.

C# 11.0

string json = """
{
    "name": "Alice",
    "age": 30
}
""";

C# < 11.0 Previously, working with multi-line strings or strings with special characters required escape sequences, which could make the string hard to read and maintain.

string json = "{\n    \"name\": \"Alice\",\n    \"age\": 30\n}";

4. Enhanced Generic Math

C# 11.0 provides improved support for generic math, making it easier to write generic algorithms that work with any numeric type, building upon the System.Numerics namespace enhancements.

C# 11.0

public static T Add<T>(T a, T b) where T : INumber<T>
{
    return a + b;
}

C# < 11.0 Before C# 11.0, writing generic mathematical operations required constraints to interfaces like IComparable, IFormattable, etc., or custom interfaces, and often involved runtime checks and casting, which was less efficient and more cumbersome.

public static T Add<T>(T a, T b) where T : IComparable, IFormattable
{
    dynamic x = a, y = b;
    return x + y;
}

5. Static Abstract Members in Interfaces

C# 11.0 allows abstract static members in interfaces, enabling polymorphic behavior on static members. This feature is particularly useful in combination with generic math.

C# 11.0

interface IAddition<T>
{
    static abstract T Add(T a, T b);
}

class IntegerAddition : IAddition<int>
{
    public static int Add(int a, int b) => a + b;
}

C# < 11.0 Previously, interfaces could not contain static members, limiting the design of certain types of generic programming patterns and requiring alternative approaches, such as using abstract classes or pattern-based designs.