Misc

Top 10 features introduced in C# 10

C# 10 brings several new features and enhancements that make it easier to write more concise, readable, and maintainable code. In this blog post, we’ll take a look at my top 10 features.

  1. File-scoped namespaces

In previous versions of C#, each file had to include a namespace declaration. C# 10 introduces file-scoped namespaces, which means you can omit the namespace declaration in each file, and the compiler will create a namespace based on the file’s directory structure.

// Old way
namespace MyCompany.MyApp.Utilities
{
    public class Helper
    {
        // ...
    }
}

// New way
namespace MyCompany.MyApp
{
    class Program
    {
        static void Main()
        {
            Helper.DoSomething();
        }
    }
}

// Helper.cs
class Helper
{
    public static void DoSomething()
    {
        // ...
    }
}

  1. Global using

C# 10 allows you to specify global using directives in a separate file, so you don’t have to include them in every file where you use them. This can help reduce clutter and make your code more readable.

// Old way
using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main()
    {
        List<string> names = new List<string> { "Alice", "Bob", "Charlie" };
        var filteredNames = names.Where(name => name.Length > 4);
        foreach (var name in filteredNames)
        {
            Console.WriteLine(name);
        }
    }
}

// New way
// using System; using System.Collections.Generic; using System.Linq;
class Program
{
    static void Main()
    {
        List<string> names = new List<string> { "Alice", "Bob", "Charlie" };
        var filteredNames = names.Where(name => name.Length > 4);
        foreach (var name in filteredNames)
        {
            Console.WriteLine(name);
        }
    }
}

// Usings.cs
global using System;
global using System.Collections.Generic;
global using System.Linq;

  1. Interpolated strings with interpolated verbatim string

C# 10 introduces a new type of interpolated string, which is an interpolated verbatim string. It’s similar to an interpolated string but allows you to include escape characters without having to escape them.

// Old way
int x = 42;
string message = "The answer is " + x;

// New way
int x = 42;
string message = $"The answer is {x}";
string path = @"C:\Users\username\Desktop";
string message = $@"The path is: {path}";

  1. Improved lambda parameters

C# 10 allows you to omit the parameter list in a lambda expression if the parameters are not used, making the code more concise.

// Old way
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
var sum = numbers.Aggregate(0, (acc, current) => acc + current);

// New way
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
var sum = numbers.Aggregate(0, (acc, _) => acc + _);

  1. Improved null checking

C# 10 introduces a new null-checking operator, which is called the null-conditional access operator with a default value. It allows you to access a property or method on a nullable object, and if the object is null, it returns a default value instead of throwing a null reference exception.

// Old way
string? name = null;
string firstName = name != null ? name.Split(' ')[0] : string.Empty;

// New way
string? name = null;
string firstName = name?.Split(' ')[0] ?? string.Empty;

  1. Improved pattern matching

C# 10 introduces a new pattern-matching feature called a recursive pattern. It allows you to match complex object hierarchies and extract properties from them in a single expression.

// Old way
if (obj is Dictionary<string, object> dict)
{
    if (dict.TryGetValue("foo", out object? value) && value is int i)
    {
        Console.WriteLine(i);
    }
}

// New way
if (obj is Dictionary<string, object> { ["foo"]: int i })
{
    Console.WriteLine(i);
}

  1. Enhanced method signatures

C# 10 allows you to specify method parameters as read-only, which means the method can’t modify the parameter’s value. It can help prevent accidental modifications and make the code more predictable.

// Old way
void Foo(int[] numbers)
{
    // modify the numbers array
}

// New way
void Foo(in int[] numbers)
{
    // can't modify the numbers array
}

  1. Index from end

C# 10 introduces a new index syntax that allows you to index arrays and collections from the end, rather than the beginning. It can make it easier to access the last elements of an array or collection.

int[] numbers = { 1, 2, 3, 4, 5 };
int last = numbers[^1]; // equivalent to numbers[numbers.Length - 1]

  1. Constant interpolated strings

C# 10 allows you to define constant interpolated strings, which are evaluated at compile time. It can improve performance and make the code more readable.

// Old way
const string message = "The answer is " + 42;

// New way
const string message = $"The answer is {42}";

  1. Enhanced using statements

C# 10 introduces a new using declaration syntax that allows you to declare and initialize a disposable object in a single statement. It can make the code more concise and easier to read.

// Old way
using (var stream = new FileStream("data.txt", FileMode.Open))
{
    // use the stream
}

// New way
using var stream = new FileStream("data.txt", FileMode.Open);
// use the stream

In conclusion, C# 10 brings several new features and enhancements that make it easier to write more concise, readable, and maintainable code. Also, there are more great features and enhancements but this post was getting too big.