Microsoft haven’t committed to anything in C# 4 yet. However, there have been hints about what they’ve been considering in Eric Lippert’s blog, and more than hints in Charlie Calvert’s blog. There’s not a lot to go on yet, but:
Most of Eric’s posts about immutability have so far been about immutable data structures. However, the first post in the series did mention that they’re playing around with immutability from the point of view of potential language support. Joe Duffy also wrote about immutability at roughly the same time.
What can we expect in terms of support? Possibilities:
- Compiler checking via attributes, as per Joe’s posts
- Immutable collections to make it easier to sensibly embed collections within immutable types
- Readonly automatic properties (as I mentioned in part 1 – I’ll expand on this in the next post)
I’m not sure what could be usefully added beyond those. One possibility, however: what about automatic equality and hashcode generation? I touched on this last time when talking about “instant data types” but I don’t see why it shouldn’t be applicable in general. After all:
- Immutable types are good candidates for dictionary keys – or to put it the other way round, using mutable types as dictionary keys is a risky idea
- If all immutable types automatically override GetHashCode and Equals, and immutable types can only compose other immutable types, everything should just work
- The obvious implementation of Equals and a “multiply, add, repeat” implementation of GetHashCode are pretty reasonable for many, many types. You could always manually override the methods if necessary.
One downside: Equality doesn’t really work well when there’s an inheritance hierarchy involved. Read Josh Bloch’s “Effective Java” for a detailed discussion. (Ooh, new edition coming out soon. Should make for great reading.)
Once again, Eric has posted rather a lot on this, concentrating on two aspects: interfaces and delegates. I believe these are already supported in the CLR (I’m sure interfaces are, and I suspect delegates are too).
Just to be clear, I don’t think anyone should expect unsafe covariance/contravariance. The following code still won’t compile (at least unless things go very differently to how I expect):
IList<string> strings = new List<string>();
IList<object> objects = strings;
objects.Add(new object()); // Oww!
This code, however, would be okay, due to the “readonly” nature of iteration:
IEnumerable<string> strings = new List<string>();
IEnumerable<object> objects = strings;
That’s the interface side. For delegates, this would probably be possible:
Action<object> objectAction = (x => Console.WriteLine(x));
Action<string> stringAction = objectAction;
// Covariance of returns (and output parameters?) from delegates
Func<string> stringFunc = () => “foo”;
Func<object> objectFunc = stringFunc;
All of this is conceptually good. It’s more for people to understand, of course, but it’s still a useful thing to have available.
This one really surprised me – to the extent that I’ll now need to edit the last chapter in the book so as not to look stupid when it’s published. (It’s fine to be wrong when predicting the future, but making a prediction which has already been proven false before publication is embarrassing.) I expected C# to stay fully static forever. However, it looks like the C# team is at least strongly considering making dynamic calling support available. Read the blog for more details, but note what isn’t included: C# reacting dynamically. In other words, Ayende’s beloved
IDynamicObject support isn’t being proposed (at the moment) – although I guess there’s always a possibility that the DLR support will somehow be available through “normal” C# without extra compiler support.
This will disappoint some people of course, but I’m happy enough. I can’t see myself using the new support particularly often, and I’m slightly worried at the extra complexity required in the language spec to explain what it will actually do, but I’m likely to treat it in roughly the same way as unsafe blocks – something to ignore most of the time.
As you can see, there’s not a lot really on the table yet. That in itself is quite interesting, however – as well as the nature of the changes. I believe that the changes from C# 3 to 4 will be much more like those from 1 to 2 than 2 to 3. Think about when VS 2005 was released – C# 3 extensions were already available in CTP form for the VS 2005 beta. Here we are with VS 2008 having RTM’d a while ago, and we only have a few ideas to mull over. Now, I’m sure that there are implementations of all of the above features and almost certainly more – but they’re not putting them out just yet. Hopefully we’ll learn more over the next few months.
The big difference with C# 3 was that there was a grand plan: LINQ. Almost every feature in C# 3 (basically not automatic properties or partial methods) supports LINQ in some way or other. I don’t see a big plan for C# 4. That’s a very good thing, in my view. We need time – quite a lot of time, I suspect – to digest LINQ. Awful as the phrase is, LINQ has the potential to be a paradigm shift in development. Those shouldn’t come along too often. Disparate changes can still be incredibly useful of course, so let’s not lack ambition for C# 4 – but I’m expecting idiomatic C# 4 to still be roughly similar to idiomatic C# 3, which certainly couldn’t be said of C# 3 to C# 2.
Only one more post in the immediate future: my own ideas for C# 4 (or at least those which I’ve come up with independently, even if others have mentioned them too).