NDepend Blog

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

November 30, 2017 9 minutes read

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 with the upcoming release of C# 8, the language 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:

  1. Extension Everything
  2. Default Implementations on Interfaces
  3. Nullable Reference Types
Want to make sure you’re staying current with good development practice as the C# language evolves?

Download the NDepend trial for free and get a grade on your codebase’s technical debt.

1. 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.

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 C# 8 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.

2. 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 will now 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.

3. 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?

NDepend helps you see issues with your code around issues like immutability, code smells, and visibility. Nullable types figure to have interesting implications for your code.

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 C# 8 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

C# 8 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.

Additional Reading

If you’re enjoying this treatment of C# 8.0 Features, check out two additional posts addressing additional features:

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. Which features does require you to look at the implementation to understand?

      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. DAVID KENNEDY says:

      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.

    1. It is called evolution. You can still use c# as c# v1.0 if you want.

  6. Dan Sutton says:

    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 get the feeling that C# is in decline, on google trends it has C# as half as popular as it used to be – probably due to the FrontEnd web languages like Angular etc. I think C# is getting more complex but its nearly at a stage now where I can use the language. It’s like C# is a language almost thought through.

    c# on google trends:
    https://trends.google.com/trends/explore?date=all&q=c%23

    1. It is getting better than ever.

  8. 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”.

  9. Kolya Ivankov says:

    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.

  10. David Kyle says:

    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.

  11. Jeff Humphreys says:

    Multiple inheritance is real. Accept it. We have to bite off chunks with things like attributes and traits and default interfaces and mixins and decorators, but we’ll get there eventually. Modeling reality means that complexity cannot be avoided, only contained – and even then only until reality trumps us again.

    Why do programmers fear change?

    1. Because they need to learn more, I guess. It is only a new feature, and it is optional.

  12. Nullable reference type is intended to help in finding and fixing the null related bugs before run time.

  13. I like default methods in interfaces but I think using them to enable a programmer to…
    “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”
    is an appalling reason to use them
    The existing clients may not be ‘forced’ to implement the logic but nevertheless it now exists in a class where it adds no value and may well be executed by mistake. Maintainers, also, won’t know if it is supposed to be used or not
    Don’t be so lazy. Design a segregated interface for the new default logic and implement it in the classes that require it

  14. C# continues to get better and better. Kudos to Microsoft, Mads, and the contributors to the open source C#.

    And thanks to Microsoft for making C# open source — feels like a big cultural change in the Satya era from prior leadership. And also thanks to Microsoft for bringing Xamarin into the fold and not mussing it up. Actually, not only did Microsoft not muss up the acquisition, they’ve done an outstanding job at improving it, and being good stewards of it.

    I wish I had all these newfangled capabilities when I was programming in C# nine years ago!

    For the C# developers who are on the .Net or Mono platforms, and have considered trying F#: let me put plug in for The Book of F# by Dave Fancher. I thought the book was a great introduction to F#. I’m just a fan of it after having read a half-dozen F# books; I’m not affiliated with it.

  15. Francesca Yffelti says:

    I agree with Kolya Ivankov in that C# might benefit from a broader pattern of operator overloading. I find it illogical that I cannot overload the ‘=’ or ‘+=’ operator and often just miss the feature. In C++ you can do almost everything, as is well known. Speaking of C++, a ‘dummy’ constructor like ‘MyClass mc;’ (where MyClass is a class, and no ‘new’ and no parentheses) would also be handy, in my view.

    I share doubts about the utility of default implementation of interfaces. For me, an interface is a thing of design, not of an implementation, and to mix these two realms seems counterproductive to me, with all consequences. And yes, it would blur the concept of non-multiple inheritance.

    Indexes and ranges are most welcome, at last!

  16. C# Needs to get itself into popular tools Blender3d etc and kick out shit like the white space rot that is python,

    Would love to see the end of JavaScrap and Python, they are both equally awful and broken scripting languages that way too many people bother with. I’d gladly prefer to use C# in all the areas that both those script languages are used and I’m sure its runtime compilation of C# would make it even faster not to mention so much much more manageable and readable.

  17. Nullable reference types – shiny cool feature. But good luck with applying it to 100 000+(or much more) lines of existing code bases.
    Besides I do love F# and think that MS should encourage using it rather than putting everything into C#. For many cases it is better language than C#.

    Default members in interface – hello multiple inheritance and all issues coming along. Especially with changes to implementation. I know that in theory such changes shouldn’t provoke side effects but we all know the reality.
    Also taking into account amount of code written in plain C (no OOP language features), C#, old java without multiple inheritance. I don’t think this feature is something really critical. Maybe some people are used to having it everywhere (but on many C++ projects I dealt with pull requests with multiple inheritance will be rejected).

    On top of that extension methods were just fine. Need extra features – add library. No need to pollute interface itself.

    Extension all – great feature stolen from Scala :). Significant code base reduction for many cases.

Comments are closed.