It was not that long ago when we published our first post about the future of C# 8.0 and the probable features it’s getting. On the first post, we covered extension everything, default implementation on interfaces, and nullable reference types.
A couple of months later, we published the second installment in the series where we covered null coalescing assignment and records.
Now it’s time for a final glimpse into the future. Today we’ll cover another two possible C# 8.0 features: target-typed new expressions and covariant return types.
Target-Typed “New” Expressions
This is a post about C#, but let me start this section by talking a little bit about Python. The famous poem “The Zen of Python” states that “Explicit is better than implicit.”
I tend to generally agree with that statement, but there are plenty of instances where leaving things as implicit can lead to clean and concise code. A classic example in C# would be type inference, which was added to the language way back in version 3.0.
By using type inference, you can omit the type name when declaring a variable.
1 2 |
Foo foo = new Foo(); var foo2 = new Foo(); |
While the first version is undoubtedly more explicit, the second feels a lot less redundant. Type inference can also be very useful in situations like LINQ queries where you don’t know or care about exactly what the return type is. And of course, it’s essential when using anonymous objects.
C# performs other types of inference as well. For instance, there’s array type inference where you can omit the type of the array’s elements. So, instead of this,
1 |
var n = new int[] { 1,2,3}; |
you can write this,
1 |
var n = new [] { 1,2,3}; |
and everything will work great.
While C#’s type inference isn’t as powerful as F#’s, for instance, it’s still a great addition to the language (and one of the features I miss the most when I have to code in other languages that don’t have it).
The trend continued. C# 7.1 presented us with default literals. This feature allows you to omit the type when using the default keyword. So code like this
1 |
int x = default(int); |
can be simplified to this.
1 |
int x = default; |
The same thing happened here as in the previous example: it’s a little bit less explicit, but also less redundant.
Now it seems C# is going to take yet another step in that direction with this new feature. Let’s start with an example.
1 2 3 |
Dictionary<string, List<string>> musicians = new Dictionary<string, List<string>> { { "John", new List<string>() { “guitar”, “bass” } } }; |
Nothing is necessarily wrong with this line, but we could get rid of the redundancy. How do we go about that?
Currently, we could rely on type inference.
1 2 3 |
var musicians = new Dictionary<string, List<string>> { { "John", new List<string>() { “guitar”, “bass” } } }; |
That’s better! We haven’t gotten rid of all the redundancy, though. But we’ll be able to do that by using the C# 8.0 feature called target-typed “new” expressions. And what is it about? In short, it enables the developer to omit the class name in a constructor when it can be safely inferred.
By employing this feature, we could rewrite the code above like this:
1 2 3 |
Dictionary<string, List<string>> musicians = new() { { "John", new List<string>() { “guitar”, “bass” } } }; |
Here, we went back to the explicit first version and then omitted the type when calling the constructor for Dictionary<string, List<string>>. We could take one more step.
1 2 3 |
Dictionary<string, List<string>> musicians = new() { { "John", new() { “guitar”, “bass” } } }; |
Is It Just Backward Type-Inference?
This may look like it’s just the same as type inference with “var” but backward. What’s the point? Well, besides eliminating redundancy when instantiating parameters, I can see this being used primarily for initializing instance fields.
Current Status
This feature is already prototyped. You can track its progress by following the official proposal.
Covariant Return Types
The community has been asking for this feature for quite a long time, and C# 8.0 may be the version that finally delivers it. What is this about? As the proposal says, it’s about allowing “an overriding method to have a more derived reference type than the method it overrides.”
Today, if you have a virtual method that returns Animal, you can’t override it with a method that returns Dog, even if it makes total sense for your domain. This proposal allows that to be legal.
If this feature were added to the language, the following code would be completely legal:
1 2 3 4 5 6 7 8 9 |
class AnimalFactory { virtual Animal Make(Options options) ... } class DogFactory : AnimalFactory { override Dog Make(Options options)... } |
Current Status
The current status for this feature is “proposed.” You can track its progress by following the official proposal on GitHub.
C# 8.0 Features: A Summary of the Glimpses
As the flagship language of .NET, C# is definitely worthy of your time. As I’ve said back in the first post, C# has changed a lot in the years since it was first released. In order to continue being relevant, it had (and still has) to be constantly evolving. Developers nowadays face a multitude of challenges that simply didn’t exist back then when the language first came to life.
At the same time, it had to remain backward compatible as much as possible since there’s already an immeasurable amount of C# code written in previous versions of the language. It had to remain faithful to its original value proposition—being an approachable C-like object-oriented language—while incorporating elements from other paradigms that made code cleaner and more declarative.
Since this is the final article in this series, let’s do a quick summary of all the features covered.
From the first post:
- Extension everything—a new syntax for extension methods that will also allow extension “other things,” like the much-anticipated extension properties.
- Default implementations on interfaces—this allows you to implement methods on interfaces, giving them a default implementation. That will enable you to add new methods to interfaces without breaking its clients.
- Nullable reference types—probably one of the most anticipated features ever. It’s a reinterpretation (a “retcon” for you comic book geeks out there) of all the reference types as nullable and the introduction of a new syntax to denote nullable types, accompanied by several types of static checks, to prevent several classes of errors regarding these types. Say farewell to the null reference exception!
From the second post:
- Null coalescing assignment—a very simple feature to shorten the check for null before assigning to a variable.
- Records—this one is pretty interesting. It’s basically a very short way for you to declare classes that are only data holders. The compiler gives you Equals and GetHashCode implementations, a constructor, properties, and immutability for free, allowing you to do something more interesting with your life than writing loads of boilerplate code.
Finally, from the current one:
- Target-typed “new” expressions—a way for you to omit the type from a constructor call, making the code simpler and less redundant.
- Covariant return types—a much-anticipated feature that allows an overriding method to return a more derived type than the original type from the base class.
What Now?
This series is over, but the wait for C# 8.0 is not. What should you, as a C# developer, do while waiting? Well, for starters, closely follow the official C# repository on GitHub. That way, you’ll stay in tune with all things C# related: important dates, features that are approved (or not), and the general direction the language is headed. There’s also a lot to learn just by reading the discussions on the proposals, the language design meetings, and so on.
And since we’ve mentioned following, if you’re on Twitter, don’t forget to follow interesting people from the C#/.NET world. For instance, by following Mads Torgersen, it’d be very hard to miss any news regarding C# development!
Last, but not least, continue hanging out here at NDepend’s blog. This series might be over, but there will always be fresh and interesting C# content here.
Comments:
Comments are closed.