In this article, I will describe each feature in C# NEXT Feature Status and demonstrating them with examples.
https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md
The milestones C# 8.1 and C# 8.2 removed from GitHub, probably to prevent speculation on a release date or which features could be released in the next version. We have seen in the last years a lot of new features. That causes a lot of troubles, and it was a big challenge for the .Net developer team. The most problems came from the legacy code or to keep the compatibility between the existing programming concepts and the new concepts.
C# NEXT, as shown below, contains the candidate features for C# 8.1 .. 8.x. Only if the candidate features in the “master” branch, that is means the feature will be released in the next version.
![](/wp-content/uploads/2019/11/image.png)
Caller Expression Attribute
Allows the caller to ‘stringify’ the expressions passed in at a call site. The constructor of the attribute will take a string argument specifying the name of the argument to stringify.
Example: https://www.c-sharpcorner.com/article/c-sharp-8-features/
Target-typed new-expressions
“var” infers the left side, and this feature allows to infer the right side.
Example:
Point p = new (x, y); ConcurrentDictionary> x = new(); Mads example: Point[] ps = { new (1, 4), new (3,-2), new (9, 5) }; // all Points
Generic attributes
Allows the generic type in the C# ‘Attributes’.
Example:
https://www.c-sharpcorner.com/article/c-sharp-8-features/
Default in deconstruction
Allows the following syntax (int i, string s) = default; and (i, s) = default;
.
Example:
(int x, string y) = (default, default); // C# 7 (int x, string y) = default; // C# 8
Relax ordering of ref and partial modifiers,
Allows the partial keyword before ref in the class definition.
Example:
public ref partial struct { } // C# 7 public partial ref struct { } // C# 8
Parameter null-checking
Allow simplifying the standard null validation on parameters by using a small annotation on parameters. This feature belongs to code enhancing.
Example:
// Before C# 1..7.x void DoSomething(string txt) { if (txt is null) { throw new ArgumentNullException(nameof(txt)); } … } // Candidate for C# 8.x void DoSomething (string txt!) { … }
Skip locals init
Allow specifying System.Runtime.CompilerServices.SkipLocalsInitAttribute as a way to tell the compiler to not emit localsinit flag. SkipLocalsInitiAttribute is added to CoreCLR.
The end result of this will be that the locals may not be zero-initialized by the JIT, which is in most cases unobservable in C#.
In addition to that stackalloc data will not be zero-initialized. That is definitely observable but also is the most motivating scenario.
Lambda discard parameters
Allow the lambda to have multiple declarations of the parameters named _. In this case the parameters are “discards” and are not usable inside the lambda.
Examples:
Func zero = (, ) => 0; (, ) => 1, (int , string ) => 1, void local(int , int );
Attributes on local functions
The idea is to permit attributes to be part of the declaration of a local function.
“From discussion in LDM today (4/29/2019), this would help with async-iterator local functions that want to use [EnumeratorCancellation]
.
We should also test other attributes:“
[DoesNotReturn] [DoesNotReturnIf(bool)] [Disallow/Allow/Maybe/NotNull] [Maybe/NotNullWhen(bool)] [Obsolete]
Basic Example:
static void Main(string[] args) { static bool LocalFunc([NotNull] data) { return true; } }
Main use case for this feature:
Another example to use it with EnumeratorCancellation on the CancellationToken parameter of a local function implementing an async iterator, which is common when implementing query operators.
public static IAsyncEnumerable Where(this IAsyncEnumerable source, Func predicate) { if (source == null) throw new ArgumentNullException(nameof(source)); if (predicate == null) throw new ArgumentNullException(nameof(predicate)); return Core(); async IAsyncEnumerable<T> Core([EnumeratorCancellation] CancellationToken token = default) { await foreach (var item in source.WithCancellation(token)) { if (predicate(item)) { yield return item; } } } }
Advanced Example:
https://gist.github.com/rynowak/4d4738a57fb482952056ca67573f1d50
Native Ints
Introduces a new set of native types (nint, nuint, nfloat, etc) the ‘n’ for native. The design of the new data types is planned to allow a one C# source file to use 32 naturally- or 64-bit storage depending on the host platform type and the compilation settings.
Example:
The native type is depending on the OS,
nint nativeInt = 55; take 4 bytes when I compile in 32 Bit host. nint nativeInt = 55; take 8 bytes when I compile in 64 Bit host with x64 compilation settings.
Function pointers
I remember the term function pointer from C/C++. FP is a variable that stores the address of a function that can later be called through that function pointer. function pointer can be invoked and passed arguments just as in a normal function call.
One of the new C# candidate features is called Function Pointers. The C# function pointer allows for the declaration of function pointers using the func* syntax. It is similar to the syntax used by delegate declarations.
Example 1:
unsafe class FunctionPointers { delegate void DAction(int a); void Example(DAction del, func* void(int) fun) { del(1); fun(1); } }
Example 2:
class LogFactory { public static void Log() { } } void* ptr = & LogFactory.Log;
Summary
You have read about the next candidate for 8.1 and 8.2 and 8.x. In the following article, I will evaluate the candidate features and write about the pros and cons.
1,205 thoughts on “C# 8 Next”