Fabulous Adventures In Coding
Eric Lippert is a principal developer on the C# compiler team. Learn more about Eric.
When we're designing a new version of the language, something we think about a lot is whether the proposed new features "hang together". Having a consistent "theme" to a release makes it easier for us to prioritize and organize proposals, it makes it easier for our marketing and user education people to effectively communicate with customers, it's just all-around goodness.
If you look at C# 2.0, it was a bit of a grab-bag. The big features were clustered around the notion of enabling rich, typesafe programming with abstract data types that represent collections of data -- and thus generic types and iterator blocks. But there was a whole lot of other stuff in there as well: implementing anonymous methods was a major feature that doesn't fit well with this theme. And there were other more minor features as well: partial classes, improvements to properties, and so on.
With C# 3.0, the theme was very clear: language-integrated query. Anything that did not directly support LINQ was immediately made lower priority. It is rather amazing to me that partial methods and auto-implemented properties got in at all; that they were relatively easy features to design, implement, test and document was what saved them.
What then is the theme of C# 4.0? Again, it seems like rather a grab-bag: covariance and contravariance, improved interop with dynamic languages, improved interop with legacy COM object models, named and optional parameters. It also seems like a pretty small set of new features compared to generics or query comprehensions.
That was deliberate. Some feedback that we received loud and clear throught the C# 3.0 ship cycle was "this is awesome, we need these language features immediately!" and, somewhat contradictorily, "please stop fundamentally changing the way I think about programming every couple years!" Rather than trying to find some way to yet again radically increase the expressiveness and power of the language, we decided to spend a cycle on making what we already have work better with the other stuff in our programming platform infrastructure.
"Now actually works the way you'd expect it to" is not really a theme that gets people excited, but sometimes you've got to stop running forward at full speed and take some time to fix the existing stuff that is annoying a lot of people. (When I was on the VSTO team I petitioned the C# team to please, please make ref parameters optional on calls to legacy COM object models, but they were too busy with designing LINQ; I'm delighted that we've finally gotten that in.)
We also want to make sure that we are anticipating the problems that people are about to face and mitigate them now. We know that dynamic languages and object models designed with dynamism in mind are becoming increasingly popular. Given that there will be stronger demand for statically typed C# to interoperate with them in the future, let's get dynamic programming interoperability in there proactively, rather than be reactive about it later.
Looking forward, it's not clear what exactly the theme of future (hypothetical!) versions of the language will be. The expected onslaught of cheap hardware parallelism looms large in our minds, so that's a possible theme. Enabling metaprogramming is another possible theme on our minds, thought it is not at all clear how that would happen. (Make C# its own metalanguage? Extend expression trees to statement trees, declaration trees, and so on? Open up the internals of the compiler and provide an object model that lets people generate programs directly? It is hard to say what direction is the right one to go in here.) Fortunately, people way smarter than I am are thinking about these things.
What about the immutability stuff you were talking about earlier this year?
Like Marcel, I was hoping for more support of concurrency-safe patterns like immutable types, etc in c# 4. Version 5 likely won't ship until at least 2012, and by then we'll all be running on 80 cores and concurrency concerns will not be "looming large" but way overdue.
I was also surprised that there isn't anything about immutable types in C# 4.0.
Well, I have been trying to message that immutability, etc, is (1) important and (2) in our future thinking, not our present thinking. Apologies if I messaged that poorly.
These things take time. A major factor in the design of work for multi-cores is that there is not a consensus in industry or academia as to what the right thing to do is. With query comprehensions, we at least had twenty years of academic research that we could look at which by and large agreed on the right way to go. With concurrent programming there are as many models as there are researchers it seems. :-)
I beg to differ on the topic of generics and anonymous delegates being unrelated. That might have been the case in design, but in practice the case is less clear.
Generics work by restricting the operations available on values of a generic type. When you want to expand on the number of available operations, you need to parameterize by the operation required. And what's the easiest way to supply operations (i.e. code) by parameters? Anonymous delegates and lambdas.
Now that the cat's out of the bag, and acknowledging that it's many months out still, periodic updates on the C#-in-C# compiler-as-a-service things Anders mentioned would be an interesting subject. I can't tell you how often I've wanted an official, sponsored full code vocabulary for talking about C# (and with dynamic programming, the cost for trying to make your own or reconcile the existing alternatives rise still). I'm very happy that not just Miguel and part of the Mono team are thinking in these terms but that Anders is involved personally in this as the language designer.
I'm happy about the C# 4 features although I would have liked more (like readonly automatic properties, an option to ignore out parameters by passing null or actual *class methods* that could be snuck into interfaces the way statics can't), but between MEF, tuples, PFX and Contracts I'm very well served by the framework improvements.
I hope everyone working on .NET are taking a second to pat themselves on the back these days. Good work!
@ Eric re: immutability and your comment of "These things take time. A major factor in the design of work for multi-cores is that there is not a consensus in industry or academia as to what the right thing to do is." I'm afraid I have to disagree. If there were to be one and only one very well-agreed-upon piece of consensus in both industry and academia, and that is that regardless of what other open issues there are around parallelism (and I admit there are plenty), it would be that the ability to declare and ensure immutability is an incredibly good thing when making any effort to go parallel, and for a myriad of reasons. And that's totally ignoring the benefits that immutable types can have even when not trying to go parallel, if only for managing side-effects in order to produce predictable behavior.
Bringing VB.net features into C# at the expense of features dedicated C# users have long been begging for (eg. non-nullable reference type variables and arguments, immutable types, etc.) is not exactly going to win any favour. Personally, I am trying as hard as I can to be happy with the gift of generic variance goodness, but it is not unlike being a child at Christmas in that it can be hard to enjoy the one good gift you might receive when you look around and all of your other gifts were grandma sweaters. ;)
This is tounge in cheek, but the truth: "*Please* fundamentally change the way I think about programming every couple years!"
I don't think that Eric intended this post as "what features do you wish we were adding in C# 4.0?", but I'm not going to pass up the opportunity to
answer that question anyway. :-)
1. Syntactic sugar for immutable data classes.
Today, if I want to make a data class, I can either take the easy route (autoprops + no ctor + object initializers), or the safe way (autoprops with private setter + ctor full of tedium + no object initializers allowed), or the very safe way (tedious get-only properties + 'readonly' fields + ctor
full of tedium + no object initializers). In the very safe way, the property/field name is mentioned 6 times, which violates DRY.
C# 4.0's named parameters reduces the need for creating multiple ctors, but the ctor is still as tedious to write as before. It also makes the "safe" and "very safe" models nicer at the call site. But I don't see anything that makes the *implementation* any nicer, so I still have to decide between easy and safe. A language change could create a "pit of success", where creating immutable data types is easy, too. (See, I said "pit of success", so now Rico will make you do it.)
2. The ability to refer to 'this' in field initializers.
I often refactor a larger class in to several smaller classes, where each one exists as a field with a specific responsibility but needs to find its way back to the main object. As the language is defined today, I have to initialize these fields in a ctor, while other fields get initialized in field initializers, making my code inconsistent and bug-prone. There are also a few patterns for converting enums to objects that are either awkward or impossible because of this language limitation, but would be great for code structure otherwise.
In both cases, it seems like a few very small changes to the language would be a big benefit, at least to me.
Eric, if you want to understand more about my thinking, drop me a mail.
Just keep to the list and everything will finally be as great as it once was :)
jQuery/ASP.NET/ASP.NET AJAX/ASP.NET MVC Visual Studio patched for better jQuery IntelliSense . Yes! Steven
> "Now actually works the way you'd expect it to" is not really a theme that gets people excited, but
> sometimes you've got to stop running forward at full speed and take some time to fix the existing stuff
> that is annoying a lot of people.
Great - so I can now call a base class method from an iterator/anonymous method in a derived class? You can't have 'fix things' as a theme unless you fix this glaring inconsistency.
Aside the parallelism/mutability theme, which will be important anyway, another good theme for C#5 could be System.Diagnostics.Contract syntax support at language level.
If I had 100 bucks to spend on various features coming in 4.0+, I would add 10 of my own and put the bet on metaprogrammability.
Re: calling base methods from anonymous methods: Yes, we fixed that.