C# 11: Preview of features for .NET 7
Published: Thursday 11 August 2022
C# 11 release date is just around the corner, and we will show what's new and preview some of the features that can be used for .NET 7.
Download .NET 7 to use C# 11
To try out the new features, we first need to download Visual Studio 2022 (version 17.3.0 or above). In-addition, we also need to download the .NET 7 SDK (version 7.0.0-preview 6 or above), so we can create a .NET 7 project.
Enable previews of the .NET SDK in Visual Studio 2022
Feature #1: Required members
The required modifier can be used in a property member to ensure that we explictly set a value when an object is initalised.
public class RequiredMember
{
public required string Name { get; set; }
}
When we initalise the object, we have to ensure that we set a value for that property. Otherwise, a compile error will be thrown:
var requiredMember = new RequiredMember { Name = "Dave" };
It's also possible to set a required member inside the object's constructor. However, we have to add an additional step.
public class RequiredMember
{
public required string Name { get; set; }
public RequiredMember(string name)
{
Name = name;
}
}
var requiredMember = new RequiredMember("Dave"); // This throws a compile error
In order to fix that, we need to set the [SetsRequiredMembers] attribute above the constructor. This tells the compiler that we are setting the required members inside the constructor.
public class RequiredMember
{
...
[SetsRequiredMembers]
public RequiredMember(string name) {
...
}
...
}
Feature #2: Auto-default structs
In C# 10, we had to explictly set the default values for each of it's members if we include a constructor in a struct.
public struct AutoDefaultStruct
{
public int Number { get; set; }
public AutoDefaultStruct()
{
Number = 0;
}
}
If we didn't set the Number property in the constructor, it would throw a compile error.
Number property will be set to 0 which is the default value of an integer.
public struct AutoDefaultStruct
{
public int Number { get; set; }
public AutoDefaultStruct()
{
}
}
Feature #3: Raw string literals
Using strings that contain quotes, or referencing code snippets like JSON have become a lot easier with C# 11.
"""...""". As a result, a single quote will be seen as being part of the string.
$ sign. The number of $ signs that are prepended to a string represents the number of curly braces required to reference a variable.
public class RawStringLiteral
{
public static int MyNumber = 1;
public string MyJsonString =
$$"""
{
"number": "{{MyNumber}}"
}
""";
}
In the above instance, we have specified two $ signs at the beginning. As a result, we need to include two curly braces to specify the variable that we wish to reference.
Feature #4: Generic attributes
With attributes in C# 10, specifying the type would involve creating a member with a Type reference, and then setting that Type reference in the constructor.
public class Attr : Attribute {
public Type AttributeType { get; }
public Attr(Type attributeType) {
attributeType = AttributeType;
}
}
public class GenericAttribute
{
[Attr(typeof(string))]
public void MyClass()
{
}
}
With C# 11, we can make these attributes generic. As a result, we don't need a separate member to reference the type. We can set the generic type to the attribute when we reference it.
public class Attr<T1> : Attribute { }
public class GenericAttribute<T1>
{
[Attr<string>]
public void MyClass()
{
}
}
A note of causion that the generic types must be fully constructed. In the above example, the GenericAttribute class has a T1 generic type. If we were to include this in the attribute, a compile error would be thrown.
public class Attr<T1> : Attribute { }
public class GenericAttribute<T1>
{
[Attr<T1>] // This throws a compile error
public void MyClass()
{
}
}
Feature #5: List patterns
List patterns allow pattern matching for elements in an array, or in a list. We have a number of options here.
public class ListPatterns
{
public bool Is_1_3_5(int[] myNumbers)
{
return myNumbers is [1, 3, 5]; // myNumbers must be a length of 3, and contain the values of 1, 3 and 5 to return true.
}
}
var listPattern = new ListPatterns();
Console.WriteLine($"Is1_3_5 = {listPattern.Is_1_3_5(new int[] { 1, 3, 5 })}"); // returns true
If we were to specify an _, it matches a single element that can be any value.
public class ListPatterns
{
public bool Is_1___5(int[] myNumbers)
{
return myNumbers is [1, _, 5]; // myNumbers must start with a value of 1, and end with a value of 5. It must also be a length of 3, but the middle index can be any value.
}
}
var listPattern = new ListPatterns();
Console.WriteLine($"Is1___5 = {listPattern.Is_1___5(new int[] { 1, 9, 5 })}"); // returns true
By specifying the .., it will match zero or more elements that can be any length.
public class ListPatterns
{
public bool Is_1_DotDot_5(int[] myNumbers)
{
return myNumbers is [1, .., 5]; // myNumbers must start with a value of 1, and end with a value of 5. There can be any values with any length between the start and end index to return true.
}
}
var listPattern = new ListPatterns();
Console.WriteLine($"Is_1_DotDot_5 = {listPattern.Is_1_DotDot_5(new int[] { 1, 9, 3, 8, 5 })}"); // Returns true
We also can specify whether a value is less than, equal, or greater than a particular value.
public class ListPatterns
{
public bool Is_1_Over_5(int[] myNumbers)
{
return myNumbers is [1, .., >=5]; // myNumbers must start with a value of 1, and the end value must be 5 or more. There can be any values with any length between the start and end index to return true.
}
}
var listPattern = new ListPatterns();
Console.WriteLine($"Is_1_Over_5 = {listPattern.Is_1_Over_5(new int[] { 1, 9, 3, 8, 6 })}");
This gives us a lot of options for checking for values in a list or an array.
Watch our demo
Watch our video where we explore the C# 11 features and how to implement them into a .NET 7 project.
In-addition, download our C# 11 features code example and use these features right now.
Related articles
Four features in C# 9 that aren't in C# 8
Looking at new features in C# 9 that aren't in C# 8. Examples like Target-Typed Object Creation and Init-Only Setters in Properties.