C# 8.x Next

This article is describing C# NEXT feature status and demonstrating with examples.

In this article, I will describe each feature in C# NEXT Feature Status and demonstrate them with examples.
 
 
The milestones C# 8.1 and C# 8.2 were 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 trouble, 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 means the feature will be released in the next version.
 
 

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
 
 

Target-typed new-expressions

 
"var" infers the left side, and this feature allows us to infer the right side.
 
Example
  1. Point p = new (x, y);  
  2.   
  3. ConcurrentDictionary<int, Queue<int>> x = new();  
Mads example
  1. Point[] ps = { new (1, 4), new (3,-2), new (9, 5) }; // all Points  

Generic attributes

 
Allows the generic type in the C# ‘Attributes’.
 
Example
 
 

Default in deconstruction

 
Allows the following syntax (int i, string s) = default; and (i, s) = default.
 
Example
  1. (int x, string y) = (defaultdefault); // C# 7  
  2.   
  3. (int x, string y) = default;                 // C# 8.x  

Relax ordering of ref and partial modifiers

 
Allows the partial keyword before ref in the class definition.
 
Example
  1. public ref partial struct { }    // C# 7  
  2.   
  3. public partial ref struct { }    // C# 8.x  

Parameter null-checking

 
Allows simplifying the standard null validation on parameters by using a small annotation on parameters. This feature belongs to code enhancing.
 
Example
  1. // Before C# 1..7.x  
  2. void DoSomething(string txt)  
  3. {  
  4.   if (txt is null)  
  5.   {  
  6.     throw new ArgumentNullException(nameof(txt));  
  7.   }  
  8. ...  
  9. }  
  10.   
  11. // Candidate for C# 8.x  
  12. void DoSomething (string txt!)  
  13. {  
  14.   ...  
  15. }  

Skip locals init

 
Allows 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
  1. Func<intintint> zero = (_, _) => 0;  
  2.   
  3. (_, _) => 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:"
  1. [DoesNotReturn]  
  2. [DoesNotReturnIf(bool)]  
  3. [Disallow/Allow/Maybe/NotNull]  
  4. [Maybe/NotNullWhen(bool)]  
  5. [Obsolete]  
Basic Example
  1. static void Main(string[] args)  
  2. {  
  3.     static bool LocalFunc([NotNull] data)  
  4.     {  
  5.       Return true;  
  6.      }  
  7. }  
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.
  1. public static IAsyncEnumerable<T> Where<T>(this IAsyncEnumerable<T> source, Func<T, bool> predicate)  
  2. {  
  3.  if (source == null)  
  4.  throw new ArgumentNullException(nameof(source));  
  5.   
  6.  if (predicate == null)  
  7.  throw new ArgumentNullException(nameof(predicate));  
  8.   
  9.  return Core();  
  10.    
  11.  async IAsyncEnumerable<T> Core([EnumeratorCancellation] CancellationToken token = default)  
  12.    {  
  13.      await foreach (var item in source.WithCancellation(token))  
  14.      {  
  15.        if (predicate(item))  
  16.        {  
  17.          yield return item;  
  18.        }  
  19.      }  
  20.    }  
  21. }  
Advanced Example
 
 

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,
  1. nint nativeInt = 55; take 4 bytes when I compile in 32 Bit host.  
  2.   
  3. 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
  1. unsafe class FunctionPointers  
  2. {  
  3.   delegate void DAction(int a);  
  4.     
  5.   void Example(DAction del, func* void(int) fun)  
  6.   {  
  7.     del(1);  
  8.     fun(1);  
  9.    }  
  10. }  
Example 2
  1. class LogFactory   
  2. {  
  3.    public static void Log() { }  
  4. }  
  5.   
  6. void* ptr = & LogFactory.Log;  

Summary 

 
You have read about the candidate features 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.