Introduction
C# 11 is the latest version of the C# programming language, released in November 2022, which is supported in .NET 7.0 and Visual Studio 2022. It has several new features and enhancements that improve the language's performance, readability, and productivity.
In this blog, we will explore C# 11 in VS 2022 with .Net 7.0 and will know some of its unique features with examples and how they can benefit developers.
Prerequisite
Visual Studio 2022 is installed on the machine; it would automatically install Microsoft .Net SDK 7 and supports C# 11.
Let us create a console application using .Net 7.0,
1. Open Visual Studio 2022
2. Select Create a New Project
3. Select Console App (Not Console App (.Net Framework))
4. Select the Project name
5. Select Framework .Net 7.0 and Create
6. Here is the default application created:
Let us explore some new features of C# 11,
1. Raw String Literals
It is a new way of writing arbitrary text, which may include white space, new lines, single quotes, double quote, or other special characters without writing escape sequences in code.
To define a raw string literal, a minimum of three double-quotes (""") characters must be used to start and end the string. Conventionally, the string is initiated with three double quotes on a single line and terminated with three double quotes on a separate line.
Let us understand this with an example:
Example 1
Code
string message = """
Writing a message
to explain "Raw String Literals"
which includes multiple lines
with different indentation and
also it contains 'single quote', "double quote",
other special chars \n and white spaces.
""";
Console.WriteLine(message);
Output
Example 2
Code
string firstName = "Aaditya Kumar";
string lastName = "Ravi";
string message = $$"""
My name is {{{firstName}} {{lastName}}}
""";
Console.WriteLine(message);
Output
Since we have used $$ ($ twice) before 3 double quotes, Hence we are using two braces opening and closing {{ }} for interpolation. The third repeated opening and closing braces are included in the output string.
2. Newlines in string interpolation expressions
Now, it is possible to write a string interpolation across multiple lines by enclosing the text within the { and } characters. The content between these markers is interpreted as C# code and can include valid C# syntax, including newlines.
Let us understand this with an example:
Example 1
Code
var filler = "WELCOME";
Console.WriteLine($"You are {filler.
ToLower()} to learn C# 11.");
Output
Here we wrote string interpolation code in multiple lines, filler. in one line and ToLower() in next to next line. Still, it is valid syntax in C# 11 and shows the expected output, it used to break in previous versions.
3. List Pattern
List patterns match sequences of elements in a list or array, allowing for matching using various patterns. For instance, if the sequence is [1, 2, 3], it will be considered true if it's an array or a list containing three integers (1, 2, and 3). This matching can be performed using any pattern, whether constant, type, property, or relational. Additionally, the discard pattern (_) matches any single element, while the new range pattern (..) matches any sequence of zero or more elements.
Let us understand this with an example:
Example 1
Code
int[] numbers = { 1, 2, 3 };
Console.WriteLine(numbers is [1, 2, 3]); // True
Console.WriteLine(numbers is [1, 2, 4]); // False
Console.WriteLine(numbers is [1, 2, 3, 4]); // False
Console.WriteLine(numbers is [0 or 1, <= 2, >= 3]); // True
Output
Each element of numbers array should match with a pattern or exact value specified in the list at the corresponding index to return True. The 0 position value of the array should match or satisfy the condition with the 0 position value of the list, 1st with 1st, and so on.
Numbers = {1,2,3} and [0 or 1, <=2, >=3], here 1 match with 0 or 1, 2 matches with <=2, 3 matches with >=3. Hence it returns True.
Example 2
Code
List<int> numbers = new() { 1, 2, 3 };
if (numbers is [var first, _, _])
{
Console.WriteLine($"The first element of a three-item list is {first}.");
}
Output
Here, the numbers list is mapped with [var first, _, _], the 2nd and 3rd position is discarded because of the underscore ( _ ), and the first value is mapped with 1 of the numbers list. Hence the first equals to 1.
Example 3
Code
int[] numbers = { 1, 2, 3 };
if (numbers is [var first, .. var rest])
{
Console.WriteLine(first);
}
Output
Here first is mapped with 1, and the remaining value is mapped with the rest variable due to slice pattern(..)
Example 4
Code
Console.WriteLine(new[] { 1, 2, 3, 4, 5 } is [> 0, > 0, ..]); // True
Console.WriteLine(new[] { 1, 1 } is [_, _, ..]); // True
Console.WriteLine(new[] { 0, 1, 2, 3, 4 } is [> 0, > 0, ..]); // False
Output
4. Required Members
By adding the "required" modifier to properties and fields, constructors and callers can be compelled to initialize those values.
Example 1
Code
var stud = new Student() {
Name = "Aaditya"
};
class Student {
public required string Name {
get;
set;
}
}
Output
Build Succeeded because we provided the value to the Name field while calling.
var stud = new Student() { Name = "Aaditya"};
If we don't provide the value to the required field, it gives an error at compile time.
Additionally, the System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute can be used with constructors to indicate to the compiler that a constructor initializes all necessary members.
Example 2
Code
using System.Diagnostics.CodeAnalysis;
static void Main(string[] args) {
Student stud = new Student("Aaditya");
}
class Student {
public Student() {}
[SetsRequiredMembers]
public Student(string name) {
Name = name;
}
public required string Name {
get;
set;
}
}
Output
The build Succeeded, as shown in the above screenshot.
5. Auto Default Struct
As part of executing a constructor, the C# 11 compiler guarantees that all fields of a struct type are initialized to their default value. Consequently, the compiler automatically initializes any field or auto property that is not initialized by a constructor. Therefore, structs that do not explicitly assign all fields in the constructor will still compile, and any fields that are not explicitly initialized will be set to their default value. Whereas C# 10 or other previous versions used to throw errors.
Example 1:Code
static void Main(string[] args) {}
public struct Coords {
public int X;
public int Y;
public Coords(int x, int y) {
X = x;
/* Y = y; here we commented Y=y assignment, still C# 11 compiles it and assign default value as
0. However C# 10 or previous version gave error at this point if all members of
struct is not assigned with some value*/
}
}
When I change project C# version 11 to 10 (by right-clicking on the project and selecting .Net 6.0), it gives an error as Y is not assigned.
Conclusion
In conclusion, C# 11 introduces a wide range of new features and improvements that make writing code easier and more efficient. The above features are just a few enhancements in C# 11, making it a great programming language for modern development. If you're a C# developer, you'll definitely want to take advantage of these new features to write more robust, efficient, and maintainable code.