NET Principal Program Manager Kathleen blogged about some of the new preview features of C# 11 that can be experienced in Visual Studio 17.1 and .NET SDK 6.0.200. Here are some excerpts to introduce some of the new features.

C# 11 Preview: Allow line breaks in “interpolation expressions” for interpolated strings

C# 11

interpolated strings (interpolated strings) is a syntax introduced in C# 6.0 that allows the insertion of expressions into strings. C#’s interpolated strings are divided into non-word-by-word and word-by-word interpolated strings ($"" and $@"", respectively). The biggest difference between the two is that non-verbatim interpolated strings, like normal strings, cannot contain line breaks in the string text and must use escapes (e.g. \r, \n). In contrast, a verbatim interpolated string can contain newlines in its text segment and will not escape newlines or other characters.

However, the “newline restriction” in non-literal interpolated strings spreads from the text of the string to interpolated expressions outside the text, which leads to many unnecessary restrictions. For example, before C# 11, the following code would compile with an error.

1
2
3
4
var v = $"Count is\t: { this.Is.A.Really()
                            .That.I.Should(
                                be + able)[
                                    to.Wrap()] }.";

However, in the C# 11 preview version, it is legal and will compile properly.

A detailed discussion of this new feature can be found in GitHub Issue #4935.

C# 11 Preview: List Mode

C# 11 Preview: List Mode

The new list pattern allows matching arrays or lists with a range of patterns, for example array is [1, 2, 3] will match an array of integers of length 3 with elements 1, 2, 3. In addition to allowing matching lists and arrays, you can also match elements, and you can choose a slice pattern that contains zero or more elements. Using the slice pattern, zero or more elements can be discarded or captured.

The syntax of a list pattern is a value enclosed in square brackets, and the syntax of a slice pattern is two dots . A slice pattern can be followed by another list pattern, such as the var pattern, to capture the contents of the slice.

For example, the pattern matches all of the following: [1, 2, . , 10].

1
2
3
int[] arr1 = { 1, 2, 10 };
int[] arr1 = { 1, 2, 5, 10 };
int[] arr1 = { 1, 2, 5, 6, 7, 8, 9, 10 };

To explore list mode, see.

1
2
3
4
5
6
7
8
9
public static int CheckSwitch(int[] values)
    => values switch
    {
        [1, 2, .., 10] => 1,
        [1, 2] => 2,
        [1, _] => 3,
        [1, ..] => 4,
        [..] => 50
    };

When it passes the following arrays, the result is shown below.

1
2
3
4
5
6
WriteLine(CheckSwitch(new[] { 1, 2, 10 }));          // prints 1
WriteLine(CheckSwitch(new[] { 1, 2, 7, 3, 3, 10 })); // prints 1
WriteLine(CheckSwitch(new[] { 1, 2 }));              // prints 2
WriteLine(CheckSwitch(new[] { 1, 3 }));              // prints 3
WriteLine(CheckSwitch(new[] { 1, 3, 5 }));           // prints 4
WriteLine(CheckSwitch(new[] { 2, 5, 6, 7 }));        // prints 50

It is also possible to capture the results of slicing patterns.

1
2
3
4
5
6
public static string CaptureSlice(int[] values)
    => values switch
    {
        [1, .. var middle, _] => $"Middle {String.Join(", ", middle)}",
        [.. var all] => $"All {String.Join(", ", all)}"
    };
  • List mode applies to any countable and indexable type – this means it has an accessible Length or Count property, and an indexer with an int or System.Index form parameter.
  • Slicing mode applies to any countable and slicable type – this means it has an accessible indexer with Range as a real parameter, or an accessible Slice method with two int formal parameters.
  • Support for the list mode is currently being considered for addition to the IEnumerable type, click here for a detailed description of this list mode.

C# 11 preview: new parameter null checking

preview: new parameter null checking

C# 11 provides a simplified syntax for verifying that a method’s argument is not null and for correctly throwing an ArgumentNullException.

Previously, variants of sample code could be used to verify that method arguments were not null.

1
2
3
4
5
6
7
8
public static void M(string s)
{
    if (s is null)
    {
        throw new ArgumentNullException(nameof(s));
    }
    // Body of the method
}

Using the new parameter null check, you can automatically perform a null check by adding ! to the parameter name to automatically perform a null check.

1
2
3
4
public static void M(string s!!)
{
    // Body of the method
}

The automatically generated null checking code will be executed before the code in the body of the method. For constructors, this null checking occurs before field initialization, calls to the base constructor, and calls to the this constructor.

A detailed description of this new parameter null checking can be found here.

How to try the preview feature

To try the preview feature in C# 11, create a C# project with LangVersion set to preview, . The csproj file is configured as follows.

1
2
3
4
5
6
7
8
9
<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net6.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
        <LangVersion>preview</LangVersion>
    </PropertyGroup>
</Project>

For more details on C# 11, check out the original blog post or discuss it via the CSharpLang repository on GitHub.