C# 8 Features

In this article, you will find some of the new C# 8 features described with pros and cons.

C# 8 is moving aggressively into the innovation world. Because of this strategy, Microsoft left many developers in a confused state. Currently, the developers have a very controversial opinion on the C# 8 new features. In this article, you can have a brief overview of the new proposed features of C# 8 language. I will describe the important features separately and demonstrate them with an example; the other less important features I will handle briefly. I will also write about the pros and cons of each important upcoming feature. Furthermore, I will give a rating score for each feature between 1 (Bad) and 10 (Excellent) and finally, I hope after reading this article, you will have a clear vision of the C# 8 Features.

The rating score is based on the below-listed criteria,
  • The technology behind: It is based on a proven and reliable technology or not?
  • Innovation: Did Microsoft do any innovation in the proposed feature?
  • My personal opinion: Based on my discussions with the communities and my expertise.

Default Interface Methods

 
Allows you to add new functionality to the interfaces of your libraries and ensure the backward compatibility with code written for older versions of those interfaces.
 
Example
  1. interface IWriteLine  
  2. {  
  3.  public void WriteLine()  
  4.  {  
  5.  Console.WriteLine("Wow C# 8!");  
  6.  }  
  7. }  
GitHub
https://github.com/dotnet/roslyn/tree/features/DefaultInterfaceImplementation
Status: Prototype 
 
Pros
You can add new functionality to the interface without breaking the compatibility with the older versions of those interfaces.
 
Cons
It should be used carefully. Otherwise, it can easily lead to violating the single responsibility principles.
 
Community
It is a very arguable feature, and it left many open discussions among the .NET community. I have handled this theme in depth in Reddit:
https://www.reddit.com/r/csharp/comments/8xg2kx/default_interface_methods_in_c_8/
 
Innovation
There is nothing new here. This concept is already applied in many languages and cloned from Java.
 
Technique behind
It is based on traits technique, and traits is a proven, powerful technique in OOP.
 
For more information about traits proof theory:
http://scg.unibe.ch/archive/papers/Scha03aTraits.pdf
 
My personal opinion
I give this feature score 3. My tip you should think before using it and ask yourself, is there any other elegant solution, which might fit better to solve your problem?
 
For more detailed information about this feature, you can read my article.
 

Nullable reference type

 
Emits a compiler warning or error if a variable that must not be null is assigned to null.
 
Example
  1. string? nullableString = null;  
  2. Console.WriteLine(nullableString.Length); // WARNING: may be null! Take care!  
  3.    
GitHub
https://github.com/dotnet/roslyn/tree/features/NullableReferenceTypes 
Status: Preview 
 
Pros
It helps you to eliminate the NullReferenceException (The Billion Dollar Mistake, ALGOL60, Tony). Moreover, it helps you to solve the problems in code like a pyramid of doom.
 
Cons
However, in complex scenarios this feature may bring some confusion in regards to reference types and using “?” character for more information, please read https://codeblog.jonskeet.uk/2019/02/10/nullableattribute-and-c-8/.
 
Community
In general, this feature is well accepted among the .NET Community.
 
Innovation
Good innovation from Microsoft.
 
Technique behind
A proven technology.
 
My personal opinion
I give this feature 9. Yes, please use it! And, get rid of the NullReferenceException!
 
More Info
https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#nullable-reference-types
 

Advanced Pattern Matching

 
Provides the ability to deconstruct matched objects, giving you access to parts of their data structures. C# offers a rich set of patterns that can be used for matching.
 
Example
  1. var point = new 3DPoint(1, 2, 3); //x=1, y=2, z=3  
  2. if (point is 3DPoint(1, var myY, _))  
  3. {  
  4.   // Code here will be executed only if the point .X == 1, myY is a new variable  
  5.   // that can be used in this scope.  
  6. }  
GitHub
https://github.com/dotnet/roslyn/tree/features/recursive-patterns 
Status: Preview
 
Pros
Recursive pattern matching helps you decompose and navigate data structures in a very convenient, compact syntax. While pattern matching is conceptually similar to a sequence of (if, then) statements, so it will help you to write the code in a functional style.
 
Cons
In complex expressions, the syntax might be tricky and difficult to understand.
 
Community
Well accepted in the .NET Community.
 
Innovation
There is nothing new here.
 
Technique behind
This is a proven and known technology, which has been used for many years especially in functional programming.
 
My personal opinion
I give this feature 9. I expected pattern matching in C# will be trendy like LINQ and Lambda expressions. This feature can be very good combined with Records to make C# syntax more functional, but I am not sure that the Records will be released in the next C# 8 version or not.
 
More Info,
https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#more-patterns-in-more-places
 

Async streams

 
Allows using ‘async’ to iterate over collections.
 
Example
  1. await foreach (var x in enumerable)  
  2. {  
  3.   Console.WriteLine(x);  
  4. }  
GitHub
https://github.com/dotnet/roslyn/tree/features/async-streams
Status: Preview
 
Pros
Async Streams provide an excellent way to represent asynchronous data sources that can be controlled by the consumer. For example, when downloading data from the web, we would like to create an asynchronous collection that returns the data in chunks as they become available.
 
Community
Well accepted.
 
Innovation
There is nothing new here! This technique is already used in many other languages Akka Streams.
 
Technique behind
Async Pull Programming Model is known and used for years.
 
My personal opinion
I give this feature 7. Please use it with the correct use cases like, downloading data from the web in chunks or getting a big query result in chunks from the database.
 
More Info,
https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#asynchronous-streams
 

Ranges

 
Ranges are a very powerful construct when it comes to accessing sequences of data or getting a slice from a collection. This feature consisting of two parts,
 
Part I Index
 
Which can be used to obtain the collection from the beginning or from the end.
 
Example
  1. Index i1 = 3; // number 3 from beginning  
  2. Index i2 = ^4; // number 4 from end  
  3. int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };  
  4. Console.WriteLine($"{a[i1]}, {a[i2]}"); // "3, 6"  
Part II Range
 
Access a sub-collection(slice) from a collection.
 
Example
  1. var slice = a[i1..i2]; // { 3, 4, 5 }  
GitHub
https://github.com/dotnet/roslyn/tree/features/range
Status: Preview 
 
Pros
Nice syntax to access sequence of data from a collection.
 
Innovation
And again, nothing is new here. A lot of similar technology is already used in other languages like Python.
 
Community
Widely accepted.
 
My personal opinion
I give this feature an 8. It can make the code more readable and understandable.
 
More Info,
https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#indices-and-ranges
 

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
  1. public static class Verify {  
  2.     public static void InRange(int argument, int low, int high,  
  3.         [CallerArgumentExpression("argument")] string argumentExpression = null,  
  4.         [CallerArgumentExpression("low")] string lowExpression = null,  
  5.         [CallerArgumentExpression("high")] string highExpression = null) {  
  6.         if (argument < low) {  
  7.             throw new ArgumentOutOfRangeException(paramName: argumentExpression, message: $ " {argumentExpression} ({argument}) cannot be less than {lowExpression} ({low}).");  
  8.         }  
  9.         if (argument > high) {  
  10.             throw new ArgumentOutOfRangeException(paramName: argumentExpression, message: $ "{argumentExpression} ({argument}) cannot be greater than {highExpression} ({high}).");  
  11.         }  
  12.     }  
  13.     public static void NotNull < T > (T argument,  
  14.         [CallerArgumentExpression("argument")] string argumentExpression = null)  
  15.     where T: class {  
  16.         if (argument == nullthrow new ArgumentNullException(paramName: argumentExpression);  
  17.     }  
  18. }  
  19. // CallerArgumentExpression: convert the expressions to a string!    
  20. Verify.NotNull(array); // paramName: "array"    
  21. // paramName: "index"    
  22. // Error message by wrong Index:     
  23. "index (-1) cannot be less than 0 (0).", or  
  24. // "index (6) cannot be greater than array.Length - 1 (5)."    
  25. Verify.InRange(index, 0, array.Length - 1);  
GitHub
https://github.com/dotnet/csharplang/issues/287
Status: Prototype
 
Pros
Less code and more readable error message.
 
Community
-
 
Innovation
Again, there is nothing new here.
 
Technique behind
Data annotation.
 
My personal opinion:
I give this feature a 5. Yes, please use it to make a better error message.
 
I will only discuss the below features in brief.
 

Default in deconstruction

 
Github
https://github.com/dotnet/roslyn/pull/25562
Status: Implemented
 
Allows the following syntax (int i, string s) = default; and (i, s) = default.
  1. (int x, string y) = (defaultdefault); // C# 7  
  2. (int x, string y) = default;               // C# 8  
Note
A lot of discussions (Microsoft developers) wish to change the syntax to (int i, string s) any= default; because here you are introducing a new variable.
 
Relax ordering of ref and partial modifiers,
 
Github
https://github.com/dotnet/csharplang/issues/946
Status: In Progress
 
Allows the partial keyword before ref in the class definition.
  1. public ref partial class { } // C# 7  
  2. public partial ref class { } // C# 8  

Null Coalescing Assignment

 
Github
https://github.com/dotnet/csharplang/issues/34
Status: In Progress
 
Simplifies a common coding pattern where a variable is assigned a value if it is null.
 
It is common to see the code of the form:
  1. if (variable == null)  
  2. {  
  3.   variable = expression; // C# 1..7  
  4. }  
  5. variable ??= expression; // C# 8 

Alternative interpolated verbatim strings

 
Github
https://github.com/dotnet/csharplang/issues/1630
Status: Master
 
This proposal will extend object initializers to allow @$"hello" as a verbatim interpolated string, compared to $@"hello" (current interpolated verbatim string).
  1. var file = $@"c:\temp\{filename}"; // C# 7  
  2. var file = @$"c:\temp\{filename}"; // C# 8  
I will consider this as a fixed bug and not a new feature, that's why I will not discuss it further.
 

Using declarations

 
Enhances the ‘using’ operator to use with Patterns and makes it more natural. 
 
Github
https://github.com/dotnet/csharplang/issues/1623
Status: Prototype
  1. // C# Oldy Style  
  2. using (var repository = new Repository())    
  3. {    
  4. // repository is disposed here!    
  5.      
  6. // vs.C# 8    
  7.      
  8. using var repository = new Repository();    
  9. Console.WriteLine(repository.First());    
  10. // repository is disposed here!  
Disposable ref structs
 
Allows you to use ref structs/read-only ref struct with ‘using’ pattern.
 
Pattern-based using for ref struct
  1. ref struct Test {  
  2.    public void Dispose() { ... }  
  3. }  
  4. using var local = new Test();  
  5. // local is disposed here!  

Generic attributes

 
Allows the generic type in the C# ‘Attributes’.
 
Github
https://github.com/dotnet/csharplang/issues/124
Status:In Progress
 
Pros
Single Responsibility Principle (SRP).
Example:
  1. public class GenericAttribute<T> : Attribute { }  
  2. public class ValidatesAttribute<T> : Attribute {}  
  3. [Validates<string>]  
  4. public class StringValidation {}  
  5. [Validates<int>]  
  6. public class IntegerValidation{}  
This feature is also coming from the community. A ten-year-old link from the community for this feature:  https://stackoverflow.com/questions/294216/why-does-c-sharp-forbid-generic-attribute-types
 

Static Local Functions

 
Allows you to add the 'static' modifier to the local functions.
 
Github
https://github.com/dotnet/csharplang/issues/1565
Status:In Preview
  1. int AddFiveAndSeven()  
  2. {  
  3.   int y = 5; int x = 7;  
  4.   return Add(x, y);  
  5.   static int Add(int left, int right) => left + right;  
  6. }  

This feature will help you to fix the warning so that it does not capture reference to any variables from the enclosing scope.

Summary

 
C# 8 has many useful new features, which are well accepted among the community; unfortunately, the innovation is still low and does not meet many developer's expectations.
 
The most upcoming new features are very useful as shown in the chart below “C# 8 Features”, the well-scored feature can make your code better, safer. and cleaner.
 
C# 8 Features

Thank you for your patience to read this article. You have read an overview of the C# 8 proposed features with their pros and cons, and I hope that will help you to be better oriented to use them in the future.