Page 21 - MSDN Magazine, February 2018
P. 21

8.0, however, the C# language team is setting out with the inten- tion of improving it. Specifically, they hope to do the following:
• Provide syntax to expect null: Enable the developer to explicitly identify when a reference type is expected to contain nulls—and, therefore, not flag occasions when it’s explicitly assigned null.
• Make default reference types expect non-nullable: Change the default expectation of all reference types to be non-nullable, but do so with an opt-in compiler switch rather than suddenly overwhelm the developer with warnings for existing code.
• Decrease the occurrence of NullReferenceExceptions: Reduce the likelihood of NullReferenceException exceptions by improving the static flow analysis that flags potential occasions where a value hasn’t been explicitly checked for null before invoking one of the value’s members.
• Enable suppression of static flow analysis warning: Support some form of “trust me, I’m a programmer” decla- ration that allows the developer to override the static flow analysis of the complier and, therefore, suppress any warnings of a possible NullReferenceException.
For the remainder of the article, let’s consider each of these goals and how C# 8.0 implements fundamental support for them within the C# language.
Provide the Syntax to Expect Null
To begin, there needs to be a syntax for distinguishing when a ref- erence type should expect null and when it shouldn’t. The obvious syntax for allowing null is using the ? as a nullable declaration— both for a value type and a reference type. By including support on reference types, the developer is given a way to opt-in for null with, for example:
string? text = null;
The addition of this syntax explains why the critical nullable improvement is summarized with the seemingly confusing name, “nullable reference types.” It isn’t because there’s some new nullable reference data type, but rather that now there’s explicit—opt-in— support for said data type.
Just as with value types, reference types that allow null should be the exception—not the default.
Given the nullable reference types syntax, what’s the non-nullable reference type syntax? While this:
string! text = "Inigo Montoya"
may seem a fine choice, it introduces the question of what is meant by simply:
string text = GetText();
Are we left with three declarations, namely: nullable reference types, non-nullable reference types and I-don’t-know reference types? Ughh, No!!
Instead, what we really want is:
• Nullable reference types: string? text = null;
• Non-nullable reference types: string text = "Inigo Montoya"
This implies, of course, a breaking language change such that reference types with no modifier are non-nullable by default.
Make Default Reference Types Expect Non-Nullable
Switching standard reference declarations (no nullable modifier) to be non-nullable is perhaps the most difficult of all the require-
Further Enhancements in C# 8.0
There are three main additional areas of enhancement under consideration for C# 8.0:
Async Streams: Support for asynchronous streams enables await syntax to iterate over a collection of tasks (Task<bool>). For example, you can invoke
foreach await (var data in asyncStream)
and the thread will not block for any statements following the await, but will instead “continue with” them once the iterating completes. And the iterator will yield the next item upon request (the request is an invocation of Task<bool> MoveNextAsync on the enumerable stream’s iterator) followed by a call to T Current { get; }.
Default Interface Implementations: With C# you can imple- ment multiple interfaces such that the signatures of each interface are inherited. Furthermore, it’s possible to provide a member implementation in a base class so that all derived classes have a default implementation of the member. Unfortunately, what’s not possible is to implement multiple interfaces and also provide default implementations of the interface—that is, multiple inheri- tance. With the introduction of default interface implementations, we overcome the restriction. Assuming a reasonable default implementation is possible, with C# 8.0 you’ll be able to include
a default member implementation (properties and methods only) and all classes implementing the interface will have a default implementation. While multiple inheritance might be a side benefit, the real improvement this provides is the ability to extend interfaces with additional members without introducing a breaking API change. You could, for example, add a Count method to IEnumerator<T> (though implementing it would require iterating over all the items in the collection) without breaking all classes that implemented the interface. Note that this feature requires a corresponding framework release (something that hasn’t been required since C# 2.0 and generics).
Extension everything: With LINQ came the introduction of extension methods. I recall having dinner with Anders Hejlsberg at the time and asking about other extension types, such as properties. Mr. Hejlsberg informed me that the team was only considering what was needed for implementing LINQ. Now, 10 years later, that assumption is being re-evaluated and they are considering the addition of extension methods for not only properties, but also for events, operators and even potentially constructors (the latter opens up some intriguing factory pattern implementations). The one important point to note—especially when it comes to prop- erties, is that the extension methods are implemented in static classes and, therefore, there’s no additional instance state for the extended type introduced. If you required such state, you’d need to store it in a collection indexed by the extended type instance, in order to retrieve the associated state.
msdnmagazine.com
February 2018 17


































































































   19   20   21   22   23