|<<>>|37 of 275 Show listMobile Mode

C# 11 Features

Published by marco on

Updated by marco on

The articles Twelve C# 11 Features by Oleg Kyrylchuk and Welcome to C# 11 by Mads Torgersen (Microsoft .NET Blog) provide an excellent overview with examples of new features in C# 11, available with .NET 7.0.

I include my own notes below.

Interesting and obviously useful

“Obvious” to me, at least. The terms link to examples in one of the articles linked above.

Native UTF-8 Strings
You can now append u8 to the end of a literal string to make it UTF-8 instead of the system-standard UTF-16. For example, “Test string”u8 will be encoded by the compiler as UTF-8 and will have the type ReadOnlySpan<byte>.
Raw Strings (Here-Doc)
C# finally supports “here documents” (which have been supported in other languages like Perl or PHP for a long time). In C#, they’re called raw string literals and,
  • they begin and end with at least three double-quotes
  • can be multi-line
  • can contain unescaped everything (unless you have three double-quotes in a row, in which case, you just add more double quotes to the fences at the beginning and end)
  • support interpolation
  • and also automatically trim left indenting.

Finally, you can just pass a formatted and indented JSON into C# code, interpolate some variables, and do it all without escaping anything![1]

Abstracting over static members
“In fact .NET 7 comes with a new namespace System.Numerics chock-full of math interfaces, representing the different combinations of operators and other static members that you’d ever want to use. […] All the numeric types in .NET now implement these new interfaces – and you can add them for your own types too! So it’s now easy to write numeric algorithms once and for all – abstracted from the concrete types they work on – instead of having forests of overloads containing essentially the same code.”

See here for an example of using generic parameters in operators, or Generic Math for an example that uses some of the new interfaces, like IAdditionOperators and ISubtractionOperators.

In that vein, there are a lot more interfaces that support generalized computation, like ISpanParsable<TSelf> Interface, which “[d]efines a mechanism for parsing a span of characters to a value.”

Required members
“Another ongoing theme that we’ve been working on for several releases is improving object creation and initialization. C# 11 continues these improvements with required members.”
Generic Attributes
You can now make attributes generic and use a generic constraint to limit which types may be passed as type parameters (enforced by the compiler, rather than at runtime). E.g. [Generic<MyType>] declared an attribute of type GenericAttribute parametrized with MyType.
Extended nameof Scope
This seems like a small one, but it’s a welcome improvement. You can now use nameof with “method parameter[s] in an attribute on the method or parameter declaration.”
StringSyntaxAttribute
[Added on 03.12.2022] This one is not technically part of C#—it’s actually included in .NET 7—but it’s worth an honorable mention. You can now decorate a parameter to indicate the string-syntax that it supports. This allows IDEs to provide string-syntax-specific code-completion, highlighting, and error-handling. A good example is, of course, for regular expression patterns. While Rider and ReSharper have provided this support for certain constructors and methods (e.g. RegEx or DateTime.Format), this is a welcome standardization that gives your own APIs the same star treatment. The post What does the StringSyntaxAttribute do? includes a list of the syntaxes supported out-of-the-box. The post StringSyntaxAttribute for syntax highlighting provides examples and screenshots.

Niche Additions

A few that seem a bit dubious, but are, I guess, welcome additions, and will be useful to someone are,

List patterns
You can do some wild matching with these (i.e. numbers is [_, >= 2, _, _] returns true if numbers is a four-element list where the second element is greater than or equal to 2.
Newslines in string-interpolation patterns
I guess it’s nice that you can format complex variables inside an interpolated string, but I still think that you should just make a local variable instead. That would be more readable, in any case.
Auto-default Structs
This will allow you to define structs without being so pedantic about defining the constructor.
Unsigned Right-shift Operator
I know I’m almost certainly not going to use this one, but it nicely rounds out the support offered with the new System.Numerics interfaces and the increased generality offered by abstracting over static members (linked above).
File-scoped types
This seems kind of like an analog to unexported types declared in TypeScript, but I don’t really see myself using them very much until we get the type declaration from TypeScript as well.
Source-generated regular expressions

This feature leverages the source-generation that’s been available since .NET 5 to avoid JIT for regular expressions by generating code for it directly. It’s really great to see the .NET team getting mileage out of the features they’re adding (I’m sure this isn’t a coincidence).

For another example of source-generation, see Generating PInvoke code for Win32 apis using a Source Generator by Gérald Barré (Meziantou's Blog), which explains how to use Microsoft’s NuGet package Microsoft.Windows.CsWin32 to easily generate source for any Win32 API or type—no more writing this stuff manually!


[1]

Check out the following animation of converting an escaped string to a raw string in Rider (from the post Rider 2022.3: Support for .NET 7 SDK, the Latest From C#11, Major Performance Improvements, and More! by Sasha Ivanova (The .NET Tools Blog):