NDepend

Improve your .NET code quality with NDepend

C# 8.0 Features: A Glimpse of the Future

C# 8.0 Features: A Glimpse of the Future

It’s been almost 20 years since Microsoft released the first version of the C# language. From its inception—when some unjustly deemed it a mere Java copycat—until now, C# has had a remarkable evolution.

Nowadays, it’s frequently featured in both most used and most loved programming languages lists. You can use it to develop desktop, web, and mobile apps, and you can write code that will run in all the major operating systems. Or you can jump right onto the IOT bandwagon and write code to “smarten” your house. We live in interesting times to be a C# developer indeed.

If the present is already exciting, what about the future? Would it be possible for us to get a glimpse of what lies ahead for the language?

Of course it is. Microsoft has developed C# “in the open” for quite a while now. You can just take a look at the GitHub repo to read (and participate—why not?) in the discussions and proposals.

Today, we’ve selected three feature proposals for C# 8.0 to talk about here: extension everything, default implementations on interfaces, and nullable reference types.

Extension Everything

Extension everything is probably the least controversial of these three feature proposals, and in a certain way, it’s the least fleshed out also. So I figured it’d make a good starting point.

You’re probably familiar with extension methods, introduced in C# 3.0 in 2007. And while it’s totally possible for them to be abused, there’s no denying that extension methods, if used wisely, can be an awesome addition to the C# developer’s toolkit—not to mention they’re essential for LINQ.

At some point you may have wondered, though: why only extension methods? And you wouldn’t be alone. Extension properties, for instance, have been a desire of C# developers for quite a long time, as evidenced by this 2009 Stack Overflow question or this even older 2007(!) forum thread.

But now it seems the wait is finally coming to an end. According to Mads Torgersen, the program manager for the C# design team, a Microsoft intern proposed a new syntax for extension methods that will also allow “extension other things.

Let’s See the Code

Well, if I were you, I’d be itching to see some code. Here’s an example of an extension method using current syntax:

Nothing surprising here, right? In the original syntax, an extension method is just a static method in a static class, with the this keyword before the first parameter.

The thing is this syntax only works with methods (and, really, how could it be otherwise, since what would be the first “parameter” of a property?)

Here comes “extension everything.” This proposal suggests a new type declaration called an “extension”:

The code above is an example; as of the date of this writing, the C# team is yet to settle on a syntax.

Regardless, the example shows the creation of an extension class that extends “int.” We then declare a property as we normally do, and we’re done.

Now the caller code would be able to use the property normally:

This new feature is meant to support methods, properties, operators, and static members, at least in the beginning; events and constructors may come later.

You won’t be able to add additional state to the original instance, i.e., creating a private field in the extension class. According to Torgersen, this would add undesirable complexity in order to keep track of this new state.

Current Status

You can follow the feature development on its GitHub issue.

Default Implementation on Interfaces

I admit I was surprised—and not exactly happy—when I first heard about default implementation on interfaces in a talk Mads Torgersen gave in May 2017, at the Build 2017 Conference.

“What about record types?” I thought. “What about immutable objects? What we’re really getting is implementation on interfaces?”

You can safely guess what this feature is by its name: we’ll be able to add method implementations on interfaces. For instance:

In C# 8.0, the code above would be perfectly legal. A class implementing the interface wouldn’t need to implement the method. If some implementation of the interface decides that the default implementation doesn’t fit its needs, then it can provide its own implementation.

Besides methods, you’ll also be allowed to add bodies for indexers, properties, and event accessors. Static members such as methods, properties, and indexers will be allowed as well.

Instance state will not be allowed in interfaces, though. You’ll be able to use static fields but not instance fields. As a consequence of this, auto-implement properties won’t be allowed as well, since they automatically declare a hidden backing-field.

Use Cases

As stated in the feature proposal, the primary use case for default interface methods is to enable the developer to safely evolve an interface. You could add new methods to it and, as long as you provided a default implementation, existing clients of the interface wouldn’t be forced to implement it.

Currently, you could solve this problem with an extension method. This approach is limited, though: what if you wanted to provide a specialized version of the method for one of the implementations? Good luck with that.

That’s when default implementation shines.

Another important value proposition of default implementation on interfaces relates to Android and iOS. Since both Java and Swift offer this feature, it’s tricky to use C# to wrap Android/iOS APIs that make use of it. C# 8.0 will make it possible to wrap those APIs more faithfully.

Will Interfaces Become Abstract Classes

Sort of, but not really. As you know, there’s no multiple inheritance in languages like C# and Java, which means you can’t inherit from more than one class. On the other hand, a class is (and will continue to be) able to implement several interfaces.

Current Status

This feature is currently being prototyped. You can follow its development on the GitHub issue.

Nullable Reference Types

“What?” you may be wondering. “Shouldn’t it be ‘non-nullable reference types’?” The name of this feature can be a bit confusing, indeed. I’ll get back to that soon, but first, let me address why this is even a thing.

I bet you’re familiar with the phrase “the billion dollar mistake.” On the off-chance you’re not, the phrase refers to the null reference, and it was coined by none other than Sir Tony Hoare, the inventor of the null reference himself.

But why is that? Why is null so bad?

You could make several arguments as to why, but the biggest problem is, of course, the risk of getting the infamous null-reference exception (aka null-pointer exception in Java-land). Since everything (“everything” in the context of C# meaning all reference types) can be null, you always run the risk of getting an exception when you try to access some member of the object.

One of the biggest issues here is that the language itself lacks a syntax that would allow the author to express their intent. It isn’t possible for you to say “This parameter can never be null” or “This property may be null sometimes, and that’s ok.”

It’s common for functional languages to deal with this by having some type that represents the concept of a potential absent value, often called “Maybe” or “Option.”

The C# team decided against something like this since, according to them, it’d be the same as adding a new kind of null to the language and it’d probably make things more complex.

Let’s go back now to the naming issue. You may be thinking that I’ve got it backwards. It makes sense to talk about nullable value types since value types are non-nullable by default. But in the case of reference types, it shouldn’t, right? After all, they’ve been nullable from the beginning.

Here’s the catch: the C# design team—in a move not free of controversy—intends to make non-nullability the new default for reference types. In that sense, the “new” thing would be the nullable types.

To keep the language consistent, they propose to use the same syntax that already exists for nullable reference types—in other words, the question mark.

Enough talking. Let’s see some code!

I suppose using the infamous “Person” class in an example is the software equivalent of playing “Stairway to Heaven” in a musical instruments store—it may be a little overdone. But using a more elaborate example would be both distracting and unnecessary, so please bear with me.

Suppose we have a “Person” class with an “Age” property of type “int.” Then, we write the following method:

Even though the code above will gladly compile, it’s fragile since “p” could be null. You probably should add an “if” statement to account for that possibility, but no one will make you do that. You’re completely free to leave the code as it is.

C# 8 promises to change that by making reference types non-nullable by default. In the example above, trying to access the “Age” property would be safe, since “p” would never be null.

If you wanted “p” to be nullable, then you’d have to add a question mark to the type, as I’ve mentioned before:

Now that “p” can be null, trying to access Age isn’t safe anymore: you’ll get a warning for doing that. Want to get rid of the warning?

Just do what you (hopefully) already do today and perform a null check:

That way, a flow analysis will be performed; if the assignment line is reached, the compiler will know for a fact that “p” can’t possibly be null and will leave you alone.

Here’s another possibility:

In short, you have several options. As soon as you convince the compiler that your code offers no risk of throwing a null reference exception, the warning goes away.

Preventing Assignment from Nullable to Non-Nullable

The new version of C# will also prevent assigning from a nullable variable to a non-nullable, so the code below will result in a warning as well:

This feature will come along with a new operator called the null-ignoring operator. You’ll basically use this operator to tell the compiler that “I, the developer, know best.” There will be situations when a variable can’t possibly be null, but the compiler won’t be able to infer that.

One such example would be the use of the “string.IsNullOrEmpty()” method:

The code above will generate a warning, despite it not being possible for “bar” to be null. That’s when this operator comes in handy:

Keep in my mind that, by using this operator, you’re basically telling the compiler: “Trust me! I know what I’m doing.” So you’d better really know what you’re doing!

What about backward compatibility?

I know what you’re probably thinking by now. “That sounds nice and all, but wouldn’t this change break a lot of existing code?”

Well, of course it would. That’s why this will be an opt-in change, activated on a per-project basis

Current Status

This one is already prototyped. If you’re interested, you can download, install, and test a preview for nullable reference types right away.

As with the previous features, you can stay tuned by following the relevant proposal in GitHub.

C# Has a Future. And It Looks Awesome

So now you know a bit more about three of the features we’re probably getting with the next major version of the C# language.

As you can see, evolving the language is hard work. The language has to remain compatible with the millions (billions?) of lines of code written with it in the last 17 years. At the same time, in order to continue being relevant, it must meet the needs of developers that are facing challenges that were unimaginable years ago. And it must do all of this without losing its essence: being an easy and approachable object-oriented C-like language.

This post was written by Carlos Schults, a software developer with experience in both desktop and web development, now trying his hand at mobile.  Carlos has a passion for writing clean and concise code, and he’s also very interested in practices that help you improve your app’s health.

Published by

Erik Dietrich

I’m a passionate software developer and active blogger. Read about me at my site.

Comments:

  1. I think C# is dying, the same way as C++ is dying since functors appeard and smart pointers and Boost. When the developer has to look inside the implementation of the library he needs to use in order to use it properly, it is the time to look for a better programming language.

      1. The interfaces. you should probably allow explicit interface implementation, probably like this:

        interface IThing {
        void foo (int number);
        void bar () { foo (1); }
        }
        class ThingA : IThing {
        public void foo (int number) { Console.WriteLine(number); }
        }

        class ThingB : explicit IThing {
        public void foo (int number) { Console.WriteLine(number); }
        public void bar () { foo(2); }
        }

        1. I just realized that maybe I’m not clear enough.
          Without the explicit thingy there could be changes or optional things added to interface later causing the behavior of the code to change unknowingly. this is not good.

  2. Hi. First of all, awesome article. I just want warn you about a typo.

    The example after “One such example would be the use of the “string.IsNullOrEmpty()” method:” is the same of the fixed version with the exclamation operator.

  3. There is always a disconnect in discussions about language, runtime, and environment. C/C++ became so widespread because the ability to code for multiple platforms made learning the syntax of the language highly useful. Ditto for Java. As C# continues to be able to be used on more platforms (.NET Core was a stroke of genius), it is going to slide into the same space.

    I dislike hearing discussions about the new “hotness” in programming languages, whatever the flavor of the month is. Devs spend too much time creating libraries to provide missing core functionality, learning vagaries of syntax, and many other things. These take away from what should be the focus of development – writing clean, testable, secure, and robust code that solves a particular problem. We don’t create new spoken languages simply because we don’t like the sentence structure or punctuation rules.

    C# has the potential to become a “universal language” in that sense, and provide a standard set of tools that shift the focus toward doing good development of code, not creation of toolsets. If and when there is ever compilation of C# code into something a browser can understand, the battle is over. (Typescript is already a step in that direction, I believe)

    1. Create tools is a major principle to get better clean and secure code. So take the path given more capability for library implementers is the path to have a well covered problem domain.
      Think that the language shouldn’t take one path help life of web developer’s and destroy systems developer capabilities, this is why is better had library implementations to solve specific problem domain.

  4. Interfaces looking evermore like Scala Traits.

    The assimilation of Scala-like features into C# is relentless, and I’d argue a good thing.

  5. C# is beginning to look more and more like C++ (in terms of complexity) with every release. A lot of the problem is that in order to appease a relatively small vocal minority, it has tried to fit a lot of functional language features from F#. Many of the new features were first developed for F# and being a .NET language it provided an ideal test-bed. In trying to be a “universal language” it has lost a lot of the what made it attractive in the first place.

    Should we rename it to C#++ because that’s where it’s heading. Just because you can shove a lot of features in a language doesn’t mean you should.

  6. Cool article. C# is becoming idiomatic… very strange. I like it.

    As an old machine code programmer, I can’t resist, though: for “Even”, “value % 2 == 0” is inefficient: use “value & 1 == 0” to test if something is even: much faster to AND with 1 than to divide by 2. (sorry).

  7. I think there should be a rapid push to put C# at the forefront of the Web Assembly world for it to remain relevant. Dotnet is a perfect fit and there’s an opportunity to revolutionize the web, with this wonderful language. Otherwise, I fear it’ll fall out of favor and we’ll see Swift, Rust or something else blow right past it, pigeon-holing it as obsolete and “legacy”.

  8. As a Data Scientist working in particular in C#, I really miss an opportunity of doing arithmetic on custom objects as well as base classes in a unified way. For instance, in my project I’ve got a class Vector3D, where T had to be some kind of number, perhaps even string. However, in order to overload a + operation, I needed to use Linq.Expression, since T is considered as a generic object.

    The problem could have been solved cleanly if base types implemented some interface like ISummable, in the same spirit as IComparable. And, perhaps, all number classes could implement ISummable and ISubtractable, while String could lack ISubtractable.

    For me, this would have been much more handy that ExtensionInt and similar stuff.

  9. Am I the only one who thinks that default implementations for interfaces is a bad idea? If you need a default implementation, why not use an abstract class whose purpose is to provide a common base set of functionality with defaults while allowing more-derived types to override base members? This feature REALLY blurs the lines between the two and I frankly don’t see the benefit.

    It also is a readability concern, as no one expects an interface to contain any implementation details. I know that any feature can be abused or used incorrectly, but usually there is a positive use-case that isn’t addressed by another language feature.

Leave a Reply

Your email address will not be published. Required fields are marked *