C# 6: First reactions

It’s been a scandalously long time since I’ve blogged about C#, and now that the first C# 6 preview bits are available, that feels like exactly the right thing to set the keys clacking again. Don’t expect anything massively insightful from me just yet; I’d heard Mads and Dustin (individually) talk about some new features of C# 6 at conferences, but this is the first opportunity I’ve had to play with the bits. There are more features to come, and I suspect that the ones we’ve got aren’t in quite the shape they’ll be in the end.

First up, if you haven’t been following Build, here are some of the resources to get you going:

Firstly, the fact that Roslyn is now open source (under the Apache 2 licence, no less) – this is incredible news. I gather it’s already working under Mono (not sure whether that’s in its entirety, or just the most important parts) which can only be a good thing. I don’t know whether I’ll have the time and energy to fork the code and try to implement any little features of my own, but it’s definitely nice to know that I could. I’ll definitely try to poke around the source code to learn good patterns for working with immutability in C#, if nothing else.

I’m not going to list the C# 6 features and go through them – read the docs that come with Roslyn for that. This is more in the way of commentary and early feedback.

Initializers for automatically implemented properties and primary constructors

I’ll talk about these two together because they’re so clearly related… which is part my beef with them. Let’s start out with the positive side: for very simple cases, these really will be wonderful. For times where you’re really just trying to wrap up a bunch of values with no additional validation, it’s really great. For example, in Noda Time I have a struct that currently looks like this:

internal struct Transition : IEquatable<Transition>
{
    private readonly Instant instant;
    private readonly Offset oldOffset;
    private readonly Offset newOffset;

    // Note: no property for oldOffset 
    public Offset NewOffset { get { return newOffset; } } 
    public Instant Instant { get { return instant; } }

    public Transition(Instant instant, Offset oldOffset, Offset newOffset)
    {
        this.instant = instant;
        this.oldOffset = oldOffset;
        this.newOffset = newOffset;
    }

    // Methods
}

(In case you’re wondering: no, there’s no reason for the constructor and properties to be public within an internal struct. I’ll fix that shortly :)

In C# 6, that would be as simple as:

internal struct Transition(Instant instant, private Offset oldOffset, Offset newOffset) : IEquatable<Transition>
{
    public Instant Instant { get; } = instant;
    public Offset NewOffset { get; } = newOffset;

    // Methods
}

This example, entirely coincidentally, shows how you can generate both fields and properties from constructor parameters.

Yay for read-only automatically implemented properties (although at-declaration initialization isn’t just restricted to read-only ones), yay for read-only fields without boilerplate constructor code, and all is generally goodness. Except… a lot of my types don’t end up looking like that. There are three main issues – validation, accessibility, and structs. Validation is already mentioned in the release notes as a potential cause for concern, and that one actually can be ameliorated to some extent. Accessibility is the assumption – as far as I can see – that the primary constructor should have the same accessibility as the class itself. Struct initialization is a relatively rare issue, but one worth considering.

LocalDateTime in Noda Time highlights all three of these issues in one handy parcel. Here’s some of the code:

public struct LocalDateTime // and interfaces
{
    private readonly CalendarSystem calendar;
    private readonly LocalInstant localInstant;

    internal LocalInstant LocalInstant { get { return localInstant; } }
    public CalendarSystem Calendar
    {
        get { return calendar ?? CalendarSystem.Iso; }
    }
    internal LocalDateTime(LocalInstant localInstant, CalendarSystem calendar)
    {
        Preconditions.CheckNotNull(calendar, "calendar");
        this.localInstant = localInstant;
        this.calendar = calendar;
    }

    // Other constructors etc
}

In C# 6, I could *sort of* achieve a similar result, like this:

public struct LocalDateTime(LocalInstant localInstant, CalendarSystem calendar) // and interfaces
{
    private CalendarSystem Calendar { get; }  = Preconditions.CheckNotNull(calendar, "calendar");
    internal LocalInstant LocalInstant { get; } = localInstant;

    // Other constructors etc
}

I’ve worked around the validation, by putting it in the property initialization. That’s not too bad, but it does potentially mean that your previously-centralized validation is scattered around the code a bit more – it lacks clarity.

We now have a public constructor instead of an internal one – which in this case wouldn’t work for me at all, as LocalInstant is an internal type. In fact, LocalDateTime does have some public constructors, but quite often I create types with no public constructors at all, just private constructors and static factory methods. Unless I’ve missed some way of separating the accessibility of the constructor from the accessibility of the type, primary constructors simply won’t be applicable for those types.

Finally, the struct part. Note how the Calendar property in the original code uses the null-coalescing operator. That’s because values of structs can always be created without going through a constructor, making the validation less helpful than it would otherwise be. In Noda Time I’ve attempted to make the default values for all structs act as if they’re valid values, even if they’re not useful values. (ZonedDateTime uses a time zone of UTC in a similar fashion.) I suspect there’s no equivalent for this using read-only automatically implemented properties – but the fix here would probably be to use an "auto read-only private field" and back that with a property – not too much of a hardship.

I think what bothers me most about this pair of features is how tightly coupled they are. If you don’t want to have a primary constructor (because you want to have more logic than it allows, or because you want to change the accessibility), but still want to initialize read-only properties, you’re forced back to declaring a separate private backing field. I think it would actually be reasonable to treat read-only properties like read-only fields, and allow them to be initialized from normal constructors too. I doubt that I’ll prevail, but I’ll certainly make the point to the team. (Heck, this may be the thing I try to implement in a Roslyn fork, just for kicks. How hard can it be? ;)

Again, I want to reiterate that in simple cases – even including where there’s simple validation, using helper methods – these features will be absolutely wonderful. I’d just like to be able to use them more often than it currently looks like I’d be able to.

Using static

Hooray! We’ll be able to select extension methods from a single type instead of from a whole namespace, like I asked for in 2005. I’m not the only one who’s been badgering the team on this for a while, so it’s great to see that it’s made it. I’m not 100% keen on the fact that it looks like any other using directive – I think it would help with clarify if it were "using static …" instead, but I’m not going to beef about that. (EDIT: I see from the language design notes that this option was considered as recently as February 2014.)

Note that this will further simplify the validation in the example above – I can see myself adding a using directive for Preconditions very frequently. It will also mean that I might get round to adding a load of extension methods into NodaTime.Testing – I didn’t want to introduce one namespace per kind of extension method, but this will be much cleaner. (I’ll still use a separate namespace to shield any pre-C#-6 users from seeing a slew of them, mind you.)

Declaration expressions

The language guide has this to say near the end:

Declaration expressions take a little getting used to, and can probably be abused in new and interesting ways.

I’m going to reserve judgement here. I’m instinctively against them as I’m sure they’ll encourage out parameter usage… but I suspect that’s the point – that out parameters aren’t too bad when they’re easy to use. It still feels like a little bit of a workaround – the language is still really designed to return a single value, and out parameters help you out when you’ve got some good reason to want to return more than one value. The big question is whether returning more than one value is a good thing or not. If it’s not – if it should only be done in extremis – then we shouldn’t be making it easier. If it is a good thing, might there not be better ways of making it easier? Maybe not – aside from anything else, this is a relatively small change, compared with alternatives. It seems likely that a platform/language designed with multiple return values in mind would not use the same approach, but that ship has sailed.

The beneficial side effect is the cleaner way of using the "as" operator to both assign and test in one go, as per the example in the guide:

if ((string s = o as string) != null) { … }

While this clearly lack the joyous vulgarity of my alternative workaround:

for (string s = o as string; s != null; s = null) { … }

… I have to grudgingly say I prefer it overall.

I’m not quite egocentric enough to think that Mads specifically had me in mind with the phrase "and can probably be abused in new and interesting ways" but I’ll obviously do my best to find something.

Anything else?

The other features (exception filters, binary literals, separators in literals, indexed members and element initializers, await in catch and finally blocks, and extension Add methods) all seem fairly reasonable to me – or at least, I don’t think I have anything interesting to say about them yet. I’m hopeful that exception filters could create some really interesting mayhem due to the timing of when the condition is evaluated, but I haven’t got as far as abusing it in a genuinely glorious way yet.

Conclusion

I’m really, really looking forward to C# 6. Despite my reservations about primary constructors and read-only automatically implemented properties, they’re still my favourite features – and ones which I hope can be made more widely useful before the final release.

The question I naturally ask myself is, "Where will this make Noda Time cleaner?" (Bear in mind that I’m still just a hobbyist in C# – Noda Time is as close to a "production" codebase as I have.) I can certainly see myself updating Noda Time to require C# 6 to build (but keeping the .NET 3.5 library requirement) fairly soon after the final release – there’s plenty that will make life simpler… and more to come, I hope.

So many thanks, C# team – and I’ll look forward to the next preview!

38 thoughts on “C# 6: First reactions”

  1. Based on my experiences with go, I’d say that multiple return can be very useful (although in go it’s mostly used for errors and checks).

    C# would have to change a lot for it to work like that though.

  2. Another benefit of the declaration expressions with casting resolves the scoping issue discussed in “Casting vs as” post/comments: http://msmvps.com/blogs/jon_skeet/archive/2013/09/19/casting-vs-quot-as-quot-embracing-exceptions.aspx

    Now you can cast, assign, enter the “if” block, and not pollute your outer scope.

    Regarding Rosylin, I recall hearing from someone on the C# team about how the old C# compiler made it very difficult to implement new language features. I hope with the Rosylin rewrite, the C# team will be able to provide small CTPs more often (like the await/async CTP) to get developer feedback or even to test different ideas.

    All in all, this is a very exciting time! (And it was really, really, really fun to see live Anders push that “make public” button on the Roslyn Codeplex site!)

  3. My initial kneejerk reaction to the primary constructors was “but now I can’t prefix my private members with an underscore!”. Although I suppose that I can, but then the constructor would expose this weird MyType(int _x, int _y) to consumers of the class. Or maybe that convention is outdated anyway, but I always liked the easy visual distinction between private members and local variables.

    Other than that, I love the idea of the primary constructors (but your points are certainly valid) and also the declaration expressions. I don’t *really* see the need for that obj.$x syntax though. It’s not *wrong* per se, but it doesn’t seem like the benefits make the efforts of implementing, testing and supporting worth it, something that Eric Lippert has really drilled into my head whenever someone asked “why doesn’t C# have feature X?”. Sure, now with Roslyn it’s much easier to implement, but I hope the C# team stays very conservative in what kind of language features they add.

    What I really, really hoped to see though was a “safe navigation operator”. I thought it was on the proposed list of changes and maybe it still is, but I’d really love a syntax of obj?.Customer?.Company?.Name where every member can be safely null.

  4. “I’m not going to list the C# 6 features and go through them – read the docs that come with Roslyn for that”

    So is C# in Depth 4th Edition happening any time soon? :)

  5. The Jury is still out for me regarding initialisers for automatically implemented properties and primary constructors too. Consider that most C# is written for line of business applications, this quick win does, I fear encourage people to be lazy and avoid enforcing their invariants. So many bugs are a result of side affects because developers forget or don’t bother enforcing invariants in even simple examples like guarding against null etc.

    To help developers fall into the pit of success, the automatically implemented properties could augmented with a mechanism for invariant enforcements. Perhaps the new features around “using” can be applied to exception types, i.e.

    private CalendarSystem Calendar { get; } = InvalidCalendarSystemException.AssignOrThrow(calendar);

    At which point I’m wonder, shouldn’t such behaviour just live in the ctor?

  6. Why do you use:

    Preconditions.CheckNotNull(calendar, “calendar”);

    and not:

    Contract.Requires(calendar != null);

  7. @mycall: We don’t use Code Contracts in Noda Time, for various reasons – partly because we target .NET 3.5, and don’t want any extra dependencies.

  8. Mind explaining your first code example.

    trying to get my head around what it is actually trying to do :/

  9. @W: Which bit? And crucially, have you read the guide to the new language features first? If you haven’t then no, none of this would make sense :)

  10. Exception filters have been in VB.Net since VB.Net 1.
    I believe this is MSIL native. There seems to be quite a few v6 features which aim to bring C# to feature parity with VB.Net

  11. when I saw the new proposed features for C# 6.0 for the first time last December 2013, I thought that it was a joke. the primary constructors syntax is horrible and horribly dirty. I guess it’s not the way how the primary constructors should be declared. I’m a fan of one-private-constructor-per-class methodology preferring factory methods instead like, in Java, “Pattern.compile(…)” or most Guava methods (if there’s a method call invocation penalty for someone – it would be nice if a more fluent constructor invocation syntax could be introduced lacking the “new” keyword as Nemerle does as far as I know). automatically implemented properties, I think, might be simply written in lambda syntax instead, like “public Instant Instant => instant;” instead of “public Instant Instant { get; } = instant;”. isn’t it beautiful and probably more fluent to the proposed expression-like methods declaration? declaration expressions are very dirty too. why not an elegant solution? binary literals, digit separators, $indexer, exception filters… I don’t think someone ever wanted them.

    I think that C# 6.0 started to grow into a clumsy language. starting from C# 3.0 only dynamic, contra/covariance, and async/await are really something new. all other features are just a cheap trick – why not trying to introduce something like enums in Java, fully-supported tuples, or even something more useful? and I’m very sorry to see that my first professional language, C# I still like and respect, becomes like this

  12. Jon, that “for” loop to cast and test is the most wonderfully evil piece of code I’ve ever seen.

    I must steal it! :)

  13. @Lyubomyr: I don’t know about “cheap tricks” but I’d certainly be significantly less happy if C# didn’t have extension methods and lambda expressions, for example.

    Yes, I’d like Java-like enums too, but I’m on the fence about more tuple support. Tuples are ugly in various ways – whereas with things like primary constructors, it becomes very simple to create an immutable type with a few properties, which is clearer to use than a tuple.

    As per the post, I still have a few concerns around primary constructors – primarily the accessibility one – but I suspect they’ll be at least partly ironed out, and I’m keen on anything that makes creating immutable types simpler.

  14. ah, Jon, sorry, I meant starting from C# 4.0 inclusively. all C# 3.0 features are extremely useful, sure. for me it’s still hard to believe that binary literals, digits grouping, and so on are necessary

    concerning the tuples support, it could be one more way to return more than one result, because I still consider “ref” and “out” a little tricky for such concerns (despite they are fine to be placeholders for previously allocated data buffers), and allow parallel assignment where necessary. the tuples are awesome obfuscators, as it’s said at the Guava wiki, and I fully agree with this statement, but there are cases when tuples are simpler to use locally than creating a class/struct (even when it’s hard to name such a class or a struct)

    primary constructors. i just think that their syntax should be implemented in another way, and look like a regular constructor (if possible) or be moved to another place, something like

    class ImmutableOne : IInterface1, IInterface2
    where T : IComparable

    %A_GOOD_KEYWORD_HERE%(int a, int b)

    keeping the class declaration cleaner. Java has a similar problem where a generic class might have a long parameterization like

    class ImmutableOne implements Interface3

    vs a C# equivalent (if i’m right, since I don’t write C# code for very long)

    class ImmutableOne : IInterface3
    where T : Interface1, U : Interface2

    both current C# primary constructors and Java class parameterization are very noisy

    p.s. not sure if greater and less signs are not cut away after publishing the comment, so I’m making a little note: ImmutableOne is generic and parameterized with a T

  15. @Lyubomyr: Well other than async/await, dynamic and generic variance there *wasn’t* much added to C# 4 and 5, so there’s not much to complain about there.

    If your beef is mostly with the syntax for primary constructors rather than the ability itself, I *suspect* it’ll really just be a matter of getting used to it. I don’t mind too much either way – I can see your suggestion working too (or even it being a body-less constructor just with a semi-colon, for example) but I don’t have much problem with what’s there.

    As for binary literals and digit separators: I believe these could genuinely make some code significantly more readable *and* it has no effect outside those literals. (In other words, it’s a feature with very little cost.)

    I haven’t worked with exception filters enough to have much opinion on them yet.

  16. If I were to be honest I don’t really like the simplified Transition definition. While it is certainly less keyboard strokes there are now 2 ways to be able to something that look quite different – which everyone needs to understand.

    I’m not sure I see real advantages essentially other than saving a little bit of typing.

  17. @Ian: It’s not saving *typing* that’s the issue – it’s saving boilerplate code to get right and read each time.

    Do you object to LINQ query expressions for the same reason? LINQ has two different ways of expressing the same concepts, which everyone needs to understand… but we’ve managed to get used to that and appreciate the benefits.

  18. Hi John,

    IMO we should make a difference between features which are small “syntactic sugars” and features which give new abilities (by “new” I mean without bad design/coding patterns).

    The “using static” is great example for new ability.

    Let’s say we’re using two namespaces (from external dll resources) with the same name sharing a component with the same signature. I could never use this component from one namespace and another component from the second namespace.

    Correct me if I’m wrong – dealing with extension method , that would be a problem even when the namespaces don’t share names as i can’t use the [namespace].[class] syntax for identification.

    Thanks !! sorry for my poor english.

  19. @devo: Well extern aliases solved the “name is only unique when qualified by an assembly” back in C# 2. I’m not quite sure what this has to do with extensions methods and the new using directive form in C# 6…

  20. Take a look at this usage of declaration expression:

    public static class TupleExtensions
    {
    public static void Decompose(this Tuple tuple, out T1 first, out T2 second)
    {
    first = tuple.Item1;
    second = tuple.Item2;
    }
    }

    Usage:

    var tuple = Tuple.Create(3, “test”);
    tuple.Decompose(out var number, out var text);

  21. What’s “impressive” in “open sourcing” of Roslyn, dude? Why you’re jumping like a child with icecream? Roslyn is a BIG PROJECT, means it take YEAR at least to “deep” into coding there. Project has no proper documentation – double fail. And third, who cares about that goddamn guts of compiler? Developers of VS extensions probably – 0.0001% of all C# devs. Everybody else will continue coding on a simple C#, spitting on Roslyn team for stupid features, which is implemented instead of NECESSARY stuff. Say, “multiple return values” – way more important than “primary constructors”.

  22. @Vincent: I’m not sure why you picked the word “impressive” which I never used, but I still think the open sourcing of Roslyn is a big deal:

    – It can be used in Mono, making code analysis etc much more portable, and saving the Mono team from having to implement the same compiler again.
    – It’ll be a fascinating codebase to examine in terms of things like patterns for immutability in C#
    – It will allow language fans to *investigate* new features themselves more easily and suggest them to Microsoft, even if MS doesn’t take the actual code

    If you don’t want to do anything with it, that’s fine – but I don’t see why you need to get so apparently angry about it…

  23. It appears I’m the outlier, I don’t see anything of significance in this C# update, not based upon this article. Microsoft has hit bottom and is digging for reasons people should buy the next version of Visual Studio.

  24. Great article.

    I’m all for getting rid of boilerplate code. I wish there were good ways to get rid of the boilerplate associated with properties that send property change events.

  25. Why does no one compare compiled code execution speed, for exact-same-job Source Code,across the compared programming language(s)?

  26. Coming from C++ I’ve been longing for declaration expressions ever since.

    if ((string s = o as string) != null) { … }

    is an improvement, but why not take it all the way as in

    if (var s = o as string) { … }

    #1 is at the same time
    — going too far by allowing ugly code and weird behavior, and
    — not going far enough by still not relieving us from null hell.

    #2 can easily be defined in an unambiguous way and would do away with useless noise.

  27. @Lyubomyr: I fully agree with you. Syntax of primary constructors is really awkward in the current proposal. Unlike all the other members it suddenly gets defined outside {..} of the type code. To me they unnecessarily bloat regions where generics and base types are specified.

    I am however a big fan for a shortened version of specifying immutable types.

    @everyone: There was a language Perl. Very expressive in its form. Expressive to that extend, that code written once had to be rewritten from scratch in case of a bug, because very few could understand all the syntax sugars that Perl offered.
    With things like $ access to indexers, I afraid that C# follows the path of Perl.

  28. @julianR During the build conference I asked Mads about the ?. operator he said they are working on that, so I still have hi hopes on it. I’d love to see this feature make it to the next CTP.

  29. @zuraff At first, I also had the fear of ending up with a language full of features that nobody understands, but hey, it’s Anders! the guy have good taste and I think he is going to keep these kind of features on a leash.

    So far, I like these kind of syntax sugar features BTW. (hope they don’t take it way too far).

  30. I think one good way to separate the initialization bits from validation bits would be some syntax similar to Java initialization blocks. But I’m not quite sure if those blocks should be allowed a primary constructor is not in place.

  31. A lot of negativity in these comments- mostly from people who haven’t bothered reading in any depth about the new language features.

    I think people are getting too worked up about the primary constructor syntax. It will be useful for quick DTO types that aren’t exposed publicly- it’s certainly not a one-size-fits-all solution. Right now if I want to pass around some values together I either have to use a Tuple, which lacks any clarity as to what each piece is, or I have to write a big block of boilerplate code. I’m hoping this is a step towards easily declaring one-off types as in F#.

    The .$ index notation seems useless at first, but if you read the design notes it is intended to allow lighter weight “dynamic” type systems without using the dynamic keyword. Currently, you’d have to write a["b"]["c"]["foo"]["bar"], which not only looks bizarre but also means you get no Intellisense or autocompletion as you’re writing it.

  32. Are the fields that are specified in a primary constructor readonly? I think I’ll continue to use explicit readonly fields if not, at least for the immutable types.

  33. It is May 2014, there is surely enough syntax,verbs,constructs and commands in C# already to achieve all the processing you will ever need , combined with a bit of actual personal intelligence. So why are we seeing yet another version? It truly has become geekery for geekery’s sake and no doubt probably makes them feel they are really c#ool!!!!!( Maybe I should copyright that…?)

  34. I wished C# would become more a real dual static/dynamic language and can behave like Javascript. The dynamic keyword adds something but I think it can be better worked out.

  35. WriteLine(«Welcome to my version of Roslyn!»); – Nothing terrible ever seen!
    Give then add another denotation of the brackets:
    WriteLine(< >);
    And maybe even add aliases for command localizations:
    alias ЗаписатьСтроку = WriteLine;

    ЗаписатьСтроку(< >);

    Until the anounce date of sixth version of the C# language shown promise.
    Most who picked the language wishes to develop their program in “C++”-like programming language.
    Programmers who are wishing to use Scala or F# are very-very few!
    Instead of optimizing the compiling code and improve the quality of the language it was created another piece of trash.

    int X=>x*x;
    int X {get {x*x;}};
    var x=(var y=rand(10);y*y);
    And it increases the readability of the program…

    public double Distance => Math.Sqrt((X * X) + (Y * Y));
    At a first glance it might be confused with the delegate

    Indexed member initializer:
    new JObject { $x = 3, $y = 7 }
    and indexed member access
    c.$name = c.$first + ” ” + c.$last;
    It generally looks like a failed attempt to realize the potential of DLR.
    The next step will probably be the following:
    var n = “name”;
    c.$(n) = c.$(“first”) + ” ” + c.$last;
    But on the other hand, if field values will be stored in dictionaries within the class, then this programming language is generally not necessary. We can use JavaScript. His speed will then be the same.

    NameOf operator:
    string s = nameof(Console.Write);
    Although perhaps will finally something useful. If you do not think that there are better implementation…

Comments are closed.