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.
Important C# 8 stuff
C# 8 Features
The new C# 8 features,
- Default interface methods
- Nullable reference types
- Pattern matching enhancements
- Asynchronous streams / Asynchronous disposable
- Using declarations
- Enhancement of interpolated verbatim strings
- Null-coalescing assignment
- Static local functions
- Indices and ranges
- Unmanaged constructed types
- Readonly-Member
- Stackalloc in nested expressions
- Disposable ref structs
Default Interface Methods
It 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
- interface IWriteLine
- {
- public void WriteLine()
- {
- Console.WriteLine("Wow C# 8!");
- }
- }
GitHub
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:
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:
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
- string? nullableString = null;
- Console.WriteLine(nullableString.Length);
-
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
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
Advanced Pattern Matching
It 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
- var point = new 3DPoint(1, 2, 3);
- if (point is 3DPoint(1, var myY, _))
- {
-
-
- }
GitHub
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 among the .NET Community.
Innovation
There is nothing new here.
Technique behind
Pattern Matching 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.
You can find more information about PM in my Pattern Matching Introduction:
Async streams
Allows using ‘async’ to iterate over collections.
Example
- await foreach (var x in enumerable)
- {
- Console.WriteLine(x);
- }
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
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
- Index i1 = 3;
- Index i2 = ^4;
- int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
- Console.WriteLine($"{a[i1]}, {a[i2]}");
Part II Range
Access a sub-collection(slice) from a collection.
Example
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
Caller Expression Attribute (Not C#8, Changed to C#Next)
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
- public static class Verify {
- public static void InRange(int argument, int low, int high,
- [CallerArgumentExpression("argument")] string argumentExpression = null,
- [CallerArgumentExpression("low")] string lowExpression = null,
- [CallerArgumentExpression("high")] string highExpression = null) {
- if (argument < low) {
- throw new ArgumentOutOfRangeException(paramName: argumentExpression, message: $ " {argumentExpression} ({argument}) cannot be less than {lowExpression} ({low}).");
- }
- if (argument > high) {
- throw new ArgumentOutOfRangeException(paramName: argumentExpression, message: $ "{argumentExpression} ({argument}) cannot be greater than {highExpression} ({high}).");
- }
- }
- public static void NotNull < T > (T argument,
- [CallerArgumentExpression("argument")] string argumentExpression = null)
- where T: class {
- if (argument == null) throw new ArgumentNullException(paramName: argumentExpression);
- }
- }
-
- Verify.NotNull(array);
-
-
- "index (-1) cannot be less than 0 (0).", or
-
- Verify.InRange(index, 0, array.Length - 1);
GitHub
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 briefly.
Default in deconstruction (Not C# 8, Changed to C#Next)
Github
Status: Implemented
Allows the following syntax (int i, string s) = default; and (i, s) = default.
- (int x, string y) = (default, default);
- (int x, string y) = default;
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
Status: In Progress
Allows the partial keyword before ref in the class definition.
- public ref partial class { }
- public partial ref class { }
Null Coalescing Assignment
Github
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:
- if (variable == null)
- {
- variable = expression;
- }
- variable ??= expression;
Alternative interpolated verbatim strings
This proposal will extend object initializers to allow @$"hello" as a verbatim interpolated string, compared to $@"hello" (current interpolated verbatim string).
- var file = $@"c:\temp\{filename}"; // C# 7
- 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
It enhances the ‘using’ operator to use with Patterns and makes it more natural.
Github
Status: Prototype
-
- using (var repository = new Repository())
- {
- }
-
-
-
- using var repository = new Repository();
- Console.WriteLine(repository.First());
Disposable ref structs
It allows you to use ref structs/read-only ref struct with ‘using’ pattern.
Pattern-based using for ref struct
- ref struct Test {
- public void Dispose() { ... }
- }
- using var local = new Test();
-
Generic attributes (Not C# 8, Changed to C#Next)
It allows the generic type in the C# ‘Attributes’.
Github
Status:In Progress
Pros
Single Responsibility Principle (SRP).
Example:
- public class GenericAttribute<T> : Attribute { }
- public class ValidatesAttribute<T> : Attribute {}
- [Validates<string>]
- public class StringValidation {}
- [Validates<int>]
- public class IntegerValidation{}
This feature is also coming from the community. A ten-year-old link from the community for this feature:
Static Local Functions
Allows you to add the 'static' modifier to the local functions.
Github
- int AddFiveAndSeven()
- {
- int y = 5; int x = 7;
- return Add(x, y);
- static int Add(int left, int right) => left + right;
- }
This feature will help you to fix the warning so that it does not capture reference to any variables from the enclosing scope.
Unmanaged constructed types
In C# 7.3 and earlier, a constructed type (a type that includes at least one type of argument) can't be an unmanaged type. Starting with C# 8.0, a constructed value type is unmanaged if it contains fields of unmanaged types only.
- Public struct Foo<T>
- {
- public T Var1;
- public T Var2;
- }
Bar<int> type is an unmanaged type in C# 8.0. Like for any unmanaged type, you can create a pointer to a variable of this type or allocate a block of memory on the stack for instances of this type:
-
- var foo = new Foo <int> { Var1 = 0, Var2 = 0 },
- var bar = &foo;
-
-
- Span< Foo<int>> bars = stackalloc[]
- {
- new Foo <int> { Var1 = 0, Var2 = 0 },
- new Foo <int> { Var1 = 0, Var2 = 0 }
- };
Notes
- This feature is a performance enhancement.
- Constructed value types are now unmanaged if it only contains fields of unmanaged types.
- This feature means that you can do things like allocate instances on the stack.
Readonly-Member
It allows you to apply the readonly modifier to any member of a struct. It indicates that the member doesn't modify the state.
- public struct XValue
- {
- private int X { get; set; }
-
- public readonly int IncreaseX()
- {
-
-
-
- var newX = X + 1;
- return newX;
- }
- }
Stackalloc in nested expressions
Starting with C# 8.0, if the result of a stackalloc expression is of the System.Span<T> or System.ReadOnlySpan<T> type, you can use the stackalloc expression in other expressions:
- Span<int> set = stackalloc[] { 1, 2, 3, 4, 5, 6 };
-
- var subSet = set.Slice(3, 2);
- foreach (var n in subSet)
- {
- Console.WriteLine(n);
- }
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.
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.
C# 9 is here
This was C# 8 but C# 9 is also available now. C# 9 introduces some cool new features. Check it out here:
Deep Dive Into C# 9
About me