With C# 6 nearly complete, work has begun on the next version. Like past versions, the first step is to set an overall theme and scope for what is to come. That vision has been shared by Mads Torgersen by publishing the first set of meeting notes for the C# 7 design team.
It's important to note that the C# design team is still in charge of the language. This is not a democratic process. We derive immense value from comments and UserVoice votes, but in the end the governance model for C# is benevolent dictatorship. We think design in a small close-knit group where membership is long-term is the right model for ensuring that C# remains tasteful, consistent, not too big and generally not "designed by committee".
Working with data
The first theme is about finding better ways to work with data. Not objects, which are behaviors closed tied to their data, but just the data itself. Mads continues,
Functional programming languages are often better set up for this: data is immutable (representing information, not state), and is manipulated from the outside, using a freely growable and context-dependent set of functions, rather than a fixed set of built-in virtual methods. Let’s continue being inspired by functional languages, and in particular other languages – F#, Scala, Swift – that aim to mix functional and object-oriented concepts as smoothly as possible.
Possible C# features in this category include:
- pattern matching
- tuples
- "denotable" anonymous types
- "records" - compact ways of describing shapes
- working with common data structures (List/Dictionary)
- extension members
- slicing
- immutability
- structural typing/shapes?
Many of these features were considered for C# 6, but didn’t quite make the cut. Part of the reason they were delayed is that Microsoft is concerned about getting the interaction between the various features right.
Performance and reliability (and interop)
The last few versions of C# focused on ease of use. Language features such LINQ and async/await don’t directly make programs faster, though they do reduce the amount of effort to use better performing patterns.
For serious performance gains where CPU cycles really matter, C# needs to improve its ability to deal with interopt and memory. Interopt is easy to understand, the cheaper it is to call a native C or C++ function, the better the application will perform. This is especially true when working with libraries that are “chatty” and require many short function calls.
In regards to memory, C# currently offers few options. Data can be always copied (structs) or always stack allocated (classes), with the option to pass either by reference as a parameter. The CLR has other features to reduce unnecessary copying such as “ref returns” and “ref locals” which C# could expose. But these leads to questions such as “If a method call can return a variable as opposed to a value, does that mean you can now assign to it?”.
m(x, y) = 5;
Mads also asks, “You can now imagine getter-only properties or indexers returning refs that can be assigned to. Would this be quite confusing?”
Componentization
With .NET being pushed to new platforms and runtimes and its libraries changing at an ever increasing pace, componentization is a major concern. That said, the language isn’t going to be the driving factor, it just needs to support what’s happening elsewhere in the ecosystem.
Distribution
With cloud computing making it easier than ever to scale out, industry experts believe that distributed computing is expected to be a major focus over the next decade. We’ve already seen the beginning of that trend in NoSQL and Map-Reduce style databases.
Mads specifically calls out two areas where C# can be improved in a way that is beneficial to those building distributed systems:
Async sequences: We introduced single-value asynchrony in C# 5, but do not yet have a satisfactory approach to asynchronous sequences or streams
Serialization: we may no longer be into directly providing built-in serialization, but we need to make sure we make it reasonable to custom-serialize data - even when it's immutable, and without requiring costly reflection.
Metaprogramming
While features such as partial classes make code generation easier to work with, the tooling story isn’t that great.
But if generated parts are themselves the result of language syntax - e.g. attributes in source code, then things quickly get messy from a tooling perspective. A keystroke in file A may cause different code to be generated into file B by some custom program, which in turn may change the meaning of A. Not a feedback loop we're eager to have to handle in real time at 20 ms keystroke speed!
He theorizes that if C# offered better support for metaprogramming, developers would be less likely to turn to code generation. To this effect they want to look at:
- Virtual extension methods/default interface implementations (Java recently acquired the latter)
- Improvements to generic constraints, e.g.: ◦generic constructor constraints
- mixins or traits
- delegation
Null
The Null Reference Exception is the bane of all developers working in production support. It is very common to see in logs and has little no ability to tell you what went wrong. You might get a line number, but with chained or LINQ expressions that is often not enough to diagnose the problem.
And at this point, there is no way to retroactively introduce truly safe non-nullable reference variables. But the lack of perfection doesn’t mean C# can’t be improved in some fashion. For example, they are looking at introducing code contracts at a syntax level instead of the clumsy pseudo-method calls we currently use.