A Preview of C# 8 with Mads Torgersen

Sign in to queue

Description

I had the privilege of dropping in Mads Torgensen's office to get a sneak peek of what might be coming to C# 8. It did not disappoint! Here are some of the things he covered:

As always, the team would love your feedback!

Tag:

C#

Embed

Download

The Discussion

  • User profile image
    Ole Tolshave

    This way of dealing with nullable refererences is...ingenious. I think. Will need to chew on a bit, but you definitely had a clever idea here. Good work!

  • User profile image
    kcdiaz

    He did say 'mad' Torgersen. :D

  • User profile image
    Mkalkere

    Never tried to understand explicit interface implementation. Concise explanation by Mads Torgersen!

  • User profile image
    JonStodle

    @Ole Tolshave: This is basically how it's done in Swift, and it's really nice work with.

  • User profile image
    vb123

    extension ext extends person { }

    Looks more javaish

    extension ext : person { }

    Looks C# ish

  • User profile image
    vb123

    Great work Compiler Team, Specially for Extension class and Default interface implementation.

  • User profile image
    Neme

    I think Count() shouldn't be a property at all. I always thought of it as a verb - it has to "count" all the elements one by one, because after all we don't know the count on an IEnumerable, it has to be evaluated - that's not good for a property, which suggests you know it upfront.

    And I think it makes sense that you now have a Count property on a List, and then there's the extension method which suggest it has to count everything (I know it probably doesn't if it can cast it to something known), but on other things you don't have a Count property when the size is not known, forcing you to think about what it does and be more efficient and maybe avoid using Count() at all.

  • User profile image
    david_n_m_b​ond

    Discussing this within our dev team...

    We are already effectively using non-nullable reference types using Jetbrains' [NotNull] attribute, which gives similar Intellisense warnings.

    Using the new non-nullable reference type option, this is a much simpler, language-integrated way of achieving this.

    HOWEVER, how will an external method (e.g. from a third-party Nuget package) with the following signature be interpreted by a C#8 compiler?:

    public string GetString() {}

    Will this be considered non-nullable? If the answer is "it depends what it was compiled against", how would we know if that third party tool compiled against C#8, just by looking at the DLL/nuget package?

    Suggestion: the non-nullable version should be decorated with the equivalent of the [NotNull] attribute to expose the intent to the package consumer.

  • User profile image
    Sid

    What about code patching? This is absolutely essential for INotifyPropertyChanged and multiple different scenarios.

  • User profile image
    Kryptryx

    On the problem of backwards compatibility and gradual code improvement. What if you allowed a definition of the form:

    int! a;

    Paralleling the use of the '?' for a nullable type to explicitly indicate a non-nullable type. Then the compiler is free to issue warnings when it detects a possible use of a null value, without requiring the use of the compilation switch which will effect all declarations. This allows gradual code migration. 

    There could then be a compiler switch which selects whether to assume a 'plain' type should be assumed to be nullable, or not. With the initial release of the 8.0, this would be 'true'. A future release, this could be changed to 'false'.

  • User profile image
    Rodrigo S Andrade

    Thats a lot of work to not say the words "Type classes"

  • User profile image
    Mads​Torgersen

    @kcdiaz: He so did! And he's not the first. AND he won't be the last! :)

    @vb123: I was deliberately avoiding the `:` syntax, so that we could use that if we ever do the "implement an interface" bit I speculate about at the end.

    @david_n_m_bond: That is exactly one of the subtleties we are debating. To what extent should an assembly "opt-in" to being interpreted with non-null intent? If we choose that it should opt in, then the compiler can stick an assembly-level attribute there to that effect.

    @Kryptryx: We very deliberately avoid having a syntax for "non-nullable". In the future, good code will mostly have non-nullable in signatures, with a sprinkling (10-20%?) of nullable. At least that's our working assumption. With our current plan, such code will be beautiful. With explicit `!`, that same code will look like it's swearing at you. It's better (we think) to have a beautiful future, and deal with transitional challenges outside of the language syntax.

     

  • User profile image
    Raphael

    I think there was a misunderstanding in the discussion about explicitly implemented interface methods.
    As far as I checked, you cannot declare an explicit implementation as "private". I think the interviewer was actually thinking about "private" access modifier - while Mad(s) used it as a synonym for an explicit implementation.

  • User profile image
    George Birbilis

    I'd expect
    extension X : Y { }
    not
    extension X extends Y { }

    that is just add a new keyword like class, interface etc., but called extension

  • User profile image
    Jeff1203

    So a default implementation of an interface member doesn't explicitly add it to the implementing class if I heard that correctly. But what if I wanted to expose the default implementation as a public member of the class. How would I let the compiler know that I would want to invoke the default implementation? I hope it doesn't involve casting.

     

    interface IFoo
    {
        int Bar() => 1;
    }
    
    class Foo : IFoo
    {
        // Bar() is explicitly implemented?
    
        // what if I wanted to make it public using the implementation?
        // will we have to do this?
        public override int Bar() => ((IFoo)this).Bar();
    }

  • User profile image
    Andrei

    I guess I will have to see how nullable reference types works, for now I don't understand how it will work with existing code in the case when I have "string s"

    I don't think checking for null everywhere is good. I really do not want to check for null everywhere.
    If a reference becomes null then it's a really unexpected state, and the app will crash, which is OK.

    Moreover, sometimes a reference is obtained from database or from a webservice call. In these cases compiler won't be able to figure out.

  • User profile image
    CESAR

    This look closer to Typescript Flow Control, and also Swift in the String? flag to identify that this variable can be null.
    Overall, this is a cool thing.
    Interfaces Default Implementation... mehhh, mixed feelings about it; meaning crossing some lines about Design Pattern? - What's the point of an Abstract Class then ? - of course, I understand 1:1 inheritance vs. multiple interfaces implementations within a class.
    I am a big fan of C# and overall all this proposed upgrade is a good thing in my opinion. Keep up the great work!

  • User profile image
    Marc Rousavy

    Great work.
    I'm not really happy with the new extension syntax though, have you thought of something like specifying full the full typename to extend?
    E.g.:

    public static class Extensions
    {
    public int System.String.LengthWithoutSpaces {
    get
    {
    return ...;
    }
    }

    Or just "string.LengthWithoutSpaces"?
    I think that would make it more readable and eliminate the use of the extra "this" parameter for existing extension methods.

    Also, I think interfaces should either have members that are optional to implement but throw a NotImplementedException, or link to another class to make the interface cleaner.
    E.g.:

    interface IPerson {
    int CalculateAge() => AgeCalculator.CalculateAge
    }
    static class AgeCalculator : IPerson {
    public int CalculateAge() {
    return ..;
    }
    }

  • User profile image
    PubescentH

    Having extension classes implement interfaces would be a great addition to the language. So, what about `for` instead of `extends`, it is already a keyword

    ```
    extension Ext for Person : IEmployee
    {
    }
    ```

  • User profile image
    Stilgar

    Guys, explicit interface implementations are not private. Please try to explain it another way. Calling it private creates confusion. The method is not accessible from an instance of the class but this does not make it private. Private access modifier is responsible for encapsulation, protecting invariants and all that jazz. Explicit interface implementation serves to allow two methods with the same name in different interfaces to be implemented separately and also to avoid API pollution with methods that are not needed or named inappropriately (think of Close vs Dispose on some classes where both methods do the same thing)

  • User profile image
    Daniel Smith

    What was it Anders used to say about starting off each new language feature with a negative score before it could be added?  A few of the recent additions in 7/7.1 feel a little bit corner-casey to me, however, I'm confident all four of the above will be really strong additions to C# 8.

    Extension everything has been a long time coming, and is probably one of the most requested features since extension methods were introduced, but it looks like it'll be worth the wait to get it done right.  I really like the new dedicated syntax for this, and can see a lot of thought has gone into future extensibility of it as well.

    I'm also really impressed with the approach to solving the nullable reference problem.  It's a tough nut to crack taking into account legacy code, but it definitely feels like the right way to go.

  • User profile image
    Naoufal

    Hi @Mads​Torgersen

    Great talk and set of features for c# 8 great job guys, but i have one question about the nutshell of async feature that use some state machine to handle the states of the task that is basically an object, why we don't use an implementation of coroutines it i'll be much faster and super light and maybe it remove lot of complexity on how c# compiler handle async operations and maybe opens new perspective.

    I'll say moving async as intrinsic for c#.

  • User profile image
    AceHack

    Can you guys please host a new Lang.NEXT.  And let me know when and where so I can come :)

  • User profile image
    AceHack

    Please allow for state in extension everything.  I do this already with  System.Runtime.CompilerServices.ConditionalWeakTable<T> but it's really ugly, add some syntactic sugar here or at least tell me why you are punting on this.  Is there something I'm missing, this is like a mixin at that point, right?

    Examples:

    https://www.infoq.com/news/2015/05/CSharp-7-extension-classes

    https://digitalrumpus.wordpress.com/2016/03/13/extension-methods-weak-references-extension-pseudo-properties-in-c/

     

  • User profile image
    AceHack

    Until I saw interface extensions I wanted duck typing so bad, now structural typing is dead to me :)  I want to add interfaces after the fact.

  • User profile image
    MaxiTB

    Hi Mads,

    Regarding the extension everything syntax; I too would prefer the already familiar notation.

    Here my thought process:
    The to be extended class is pretty much similar but not equal to an base class, while interfaces extended by the extension are similar to interfaces that get implemented into a concrete class.

    So
    public sealed class Human : Person, IPersonType
    {
    bool IPersonType.IsCompany { get; }
    }

    would be visually align nicely with

    public sealed extension Company : Person, IOpeningHours
    {
    DateTime IOpeningHours.OpenFrom { get; }
    }

    while adding the next keyword expands seems a little pointless to me.

  • User profile image
    Tyler​Brinkley

    Where is the Extension Everything proposal on GitHub? I cannot find it anywhere.

    Also, for Extension Everything can the 'this' property be null as it currently can for extension methods?

  • User profile image
    Diego

    Almost all the features seems really cool, the only point I expect never leave the paper is this Default Interface Implementation.
    Interfaces should be a strict contract, Not something that you implement when you want.
    If you are planning to bring the concept of multiple inheritance why not implement it using the class inheritance, or multi inheritance of abstract classes and let the interfaces serve their own purpose.

  • User profile image
    Mikernet

    This is all very awesome. Default interface implementations would really clean up code where lots of interface functionality is optional, i.e. have default implementations like:

    bool CanWrite { return false; }
    Write(byte[] data) { throw new NotSupportedException(); }

    PLEAAASE implement the extension everything for the next release and work towards extension interface implementations. I feel like if C# got a few more really awesome features like that it would become exponentially more powerful as a language. The type system needs more flexibility to allow better organization of code in "multiple inheritance" type situations.

    One last question that is somewhat related - the framework and languages are almost 20 years old at this point and have evolved so much. Your religious devotion to maintaining backwards compatibility means there are lots of things in the framework kicking around that would have been done differently now that you have all these features available, some "mistakes" that can't be changed, and even things like class/member/interface names that are less than ideal.

    Is there any hope of ever having a reboot "clean slate" release of .NET that fixes all these legacy issues and allows the framework to remove legacy cruft and get a makeover based on all the lessons learned up to this point without having to compromise for backwards compatibility sake?

  • User profile image
    GermanKuber

    Wow. Expansion Everything is a good feature.
    Is wonderful.

  • User profile image
    Vibeeshan

    Great work compiler team!!!

    Really happy to see that new language features are added at a rapid phase than any other programming language , at the same time I am little scared that we are going to add lot of language features that are not going to get used frequently. Go forward compiler team but keep every steps carefully.

    I really think that we should keep the keyword count as low as possible. 

    Think about this two points regarding extension class.

    1. When classes and interfaces use ":" to denote that it's going to extent, why a new keyword is introduced for extensions. To separates interfaces implementations, it's same as how classes implemented, interfaces followed by base class
    2. We are introducing two keywords for one feature. Just the keyword "extension" is enough.

    This feature implementation is really inconsistent with class and interface definitions. Please consider the point, before release. Once the language is released then we can't go back. 

    We are really proud of c#'s implementation of ":" compared to two keywords in Java (extends and implements ). Please try to keep it up.

  • User profile image
    sjb

    I really started laughing when Mads said that this was going to help me by breaking my code :-) Might actually be true though.

  • User profile image
    sjb

    I would vote for either

    await foreach (var x in asyncStream) {...}

    or else

    foreach (var x in await asyncStream) {...}

    It doesn't feel intuitive to me to say

    foreach await (var x in asyncStream) { ... }.

  • User profile image
    sjb

    Some great stuff here !!

  • User profile image
    Jonney Shih

    Will we be able to write :
    Class! instance;
    to invoke the default constructor like in C++?

    Also why add a new type syntax if default reference types are already nullable?
    Adding a two new T? and T! syntaxes will risk making the plain T syntax obsolete.

    Plain vanilla types should never become obsolete in the future, simple syntax should never become redundant over fancy syntax. Haven't we learned from C++. C# would have dodged the pointer bullet just to fall in the nullability trap.

    Maybe it would be nice to have at least a compiler switch to enforce either nullability or non-nullablity for plain types in the future.

  • User profile image
    gabrielmolt​er

    @vb123:it extends not implements, I think using ":" could be confusing because of it. And as Mads said, looks like this is on early researching phase.

  • User profile image
    Carl Hjerpe

    I'm still waiting for multiple return values https://gobyexample.com/multiple-return-values, very handy language feature!

  • User profile image
    Anonymous Coward 86

    • Nullable References (opt-in)
    • Async Stream
    • Interfaces with Default Implementations
    • Extension Everything

    Fabulous!

    I worked at a company that had another team with a guy who he (and his team) had a lot of amazing, powerful enhancements to C#. Some of these C#8 features are reminiscent of the work he did, although I'm sure very different. Yay!

    They did a lot of other things that may be very suitable for C# and the runtime to consider incorporating. Such as contracts, safe native code, distinction between bugs versus errors (and recoverability), or even more powerful non-nullable references (as errors, not warnings).

    The iterations went through names like Spec#, Sing#, and M#. I think those enhancements would be wonderful candidates to make it into mainstream C#. I can send you a link to his blog that discusses their discoveries.

    For me, I've switched to F#. But I still think of C# as a powerful ally which has a lot of untapped potential.

  • User profile image
    Rasik

    The boundary between interfaces and abstract classes seem to be getting blur now. Only differentiation left would be the support of multiple inheritance which abstract classes don't allow.

  • User profile image
    Rasik

    @vb123: I second you for : in place of extends.

  • User profile image
    wiktorw

    I would also prefer:
        extension X : Y { }

    over:
        extension X extends Y { }

    However, if you really need some keyword, how about reusing "for" instead?
        extension X for Y { }

    BTW. This also reads more naturally, and avoids confusion with Java "extends" keyword.

  • User profile image
    mostafavaki​ly

    and in which version do you add anonymous classes?

  • User profile image
    repka

    @Carl Hjerpe

    You missed this feature by a couple of years, it's been since C#7:


    static (int, int) Boo()
    {
    return (1, 2);
    }

    static void Main()
    {
    var (x, y) = Boo();
    Console.WriteLine($"{x}, {y}");
    }

  • User profile image
    Tim Cooke

    I'm with everyone above about using a colon instead of extends for extension classes.

    extension PersonExt : Person
    {
    ...
    }

    But your comment is:

    I was deliberately avoiding the `:` syntax, so that we could use that if we ever do the "implement an interface" bit I speculate about at the end.

    Why introduce lousy Java-style syntax now for a possibility of adding an additional lousy `implements` keyword in the future?

    Why not keep the beautiful, C#-style colon and if - way down the road - you decide to add interface extensions, require the ugly implements keyword?

    extension PersonExt : Person implements IEmployee
    {
    ...
    }

    That way we can have a colon instead of `extends` (better syntax for now) and in C# 9 or 10, we have equivalent syntax when we add the `implements` keyword.

  • User profile image
    Mike D

    All of those are stupid, you should inherit to extend properties, you should use abstract classes for default implementations, and do I really even have to say anything about the stupid "nullable references"? If the developer is too dumb to check the reference first with the c#6 .? operator, should they really be a developer?

    Here's what yoh should do instead:
    1. Properties and methods of any null reference return null (make the compiler stick the .? operator after every reference)
    2. Fix multiple inheritance of classes.

  • User profile image
    Jonney Shih

    Don't mind my earlier comment, I saw the video, nullable types are gonna awesome.
    Very genius!

    Regarding extension what about alternative symbol syntax like:

    extension Ext : Class << Interface
    {
    }

    or:
    extension Ext of Class : Interface
    {
    }

    or anonymous extensions:

    extension Class : Interface
    {
    }

    Etc, etc...

  • User profile image
    Mikernet

    @Carl Hjerpe - Multiple return values are already done in the newest version of C#, have you been asleep? Haha :P

    @Rasik - Abstract classes are still quite a bit different than interfaces with default implementations as they are in the inheritance chain and thus can access protected members, override base class functions, etc.

  • User profile image
    Unluckeh

    Why not use the existing syntax with extensions, including the interface implementation? So just as...

    public class Bob : Alice, IPerson {}

    ...reads as "Bob extends Alice, implements IPerson"...

    extension Bob : Alice, IPerson {}

    ...would read the same way?

  • User profile image
    Anton

    Will the default implementation of interfaces be like Type Classes in Haskell? There is a minimal implementation in Haskell.

    interface IComparer<T>
    {
    Eqaul(T a, T b) { return !DoNotEqual(a,b); }
    NotEqual(T a, T b){ return !Equal(a,b); }
    }

    User is forced to implement one of the methods. The other one will be implemented automatically.

  • User profile image
    Zeleps

    The nullability warning can easily lead to false negatives in a multithreaded application. E.g.

    string? s;
    
    void SomeMethod()
    {
    if (s != null)
    {
    // another thread nullifies s, but the compiler does not produce a warning for the next line
    s.Length; //NRE
    }
    }


    Default interface implementations are really great, tackling both the multiple inheritance ambiguity problem and the unnecessary code duplication that is now necessary.

    Extension interfaces are a genius idea, they are actually a game changer in design patterns implementation.

    Keep up the good work!

  • User profile image
    Mikernet

    @Zeleps: Anyone writing multi-threaded code should recognize immediately that the code you posted isn't thread safe. I don't really see that as a nullability issue. The compiler isn't designed to stop you from writing bad MT code that can do all sorts of bad things.

  • User profile image
    Rob

    Extension interfaces would be amazing.

    Suppose we make int / double implement an INumeric interface? Would using the interface have any impact on performance? Would the compiler be able to avoid boxing?

    If extension interfaces worked at compile time, but not runtime (dynamically), that would be good enough for me.

  • User profile image
    Artem Valieiev

    Whats difference between IAsyncEnumerable<T> and List<Task<T>> in foreach case ?

  • User profile image
    Joshua Schaeffer

    I hate extension properties. They turn the code into a den of lies and scare programmers out of learning how to responsibly edit someone else's code. I will fire anyone who uses them.

  • User profile image
    humbrie

    The reason why i admire C# so much is, that the people behind it always think about how to support the development process and quality. It's not just "syntactic sugar". NullRefs are the most annoying things in modern languages. It makes you look stupid as a dev although it can be very subtle and hard to find.

     

    Great job!

Add Your 2 Cents