Fabulous Adventures In Coding
Eric Lippert is a principal developer on the C# compiler team. Learn more about Eric.
Good morning everyone! I am pleased to tell you that the C# and VB teams are announcing a "refresh" of the async Community Technology Preview at MIX11 today, and that it is as of right now available on the Async CTP site.
Recall that the CTP release is an early look at our thinking for the proposed async language features so that we can get your feedback. Rather than posting feedback here, please let us know what you think on the Async Forum.
We've gotten a lot of good feedback so far; this refresh is intended to address the top ten-or-so concerns voiced so far about the CTP, namely:
Watch Lucian's blog and the Async Forum for more details on precisely what the changes outlined above are. Also, Mads and Alex have just posted interviews on Channel 9 giving an overview of the various changes in video form. Their videos are here and here.
Some tips I've heard on getting it installed from those in the know:
I encourage you to check it out and post any thoughts or questions you might have to the forum. Thanks!
And as always, thanks to my colleagues Mads, Alex and Lucian for their leadership in this feature area, and for providing this list of changes.
Yay! Thanks for this - I can finally install SP1 :)
I've just downloaded the spec, and I can't immediately *see* any changes to the awaiter pattern compared with the previous version... can you enlighten us as to what these are? Or were they just *implementation* changes instead of spec changes? I'll be interested to see whether my solution of "async without the AsyncCtpLibrary.dll" projects still builds...
(Will try awaiting a dynamic expression as well, as I believe that will work now.)
Have worked out why I couldn't see any difference in the spec: the one I downloaded from the async CTP site today is actually the same as the old one. (At least, they have the same MD5 sum.)
Any idea if this is actually due to caching (which I've certainly seen as an issue on MSDN sites before) or just a delay in making the new spec available?
Final comment for the moment, I promise: looks like it's a client-side caching issue. Downloading in a different browser fixed it. Hope this helps anyone else downloading bits from the site.
This is not directly related question, but are you planning to fix how the foreach statement is handling clojures ?
You had a blog about it a few years back at
but I could not find any statement about it since C# 4 came up.
The foreach closure issue is certainly one I've burnt my hand on now. Interesting post. Showing a warnings seem to be the way to go. Even if the compiler can't detect a problem in the general case, a warning would certainly be beneficial where the compiler can clearly see that the delegate is getting reused outside of the loop in the scope of the local function.
It seems like a shame that await expressions can't be used in most places in query expressions because query expressions can't generate async lambdas. Is there any reason that await expressions can't just be detected and cause their enclosing lambdas to be made into async lambdas?
I'd expect that async query expressions would allow something similar to F#'s async workflows, or maybe allow nice composition with Rx.
Am I wrong? Is there no real good use case for async query expressions?
Personally I would like to see for loops changed to the iterator being inside the block (ie same as Lua), as it'd save me from having a heap of redundant variables with silly names (ie normally "j" and "localJ", or for foreach's "item" and "localItem") - which just make the code harder to understand, and I'm always afraid someone will remove the "localJ" without understanding it's purpose. Often it's in a lambda that is consumed right then and there, but I still have to copy it to a new variable just to keep ReSharper happy..
But alas, as there's probably 1 or 2 programs in the known universe that depend on the current feature (I can't imagine how or why), it'll never be changed.
My question (sorry if you've already read it at the end of the last comments thread) - any chance we can have IReadList added, an IWriteList added, an IExpandableWriteList (ie Clear, Add - array would ideally not implement this) added, and IList inherit from IExpandableWriteList and IReadList? I have a raft of classes that all only half implement the IList interface, throwing exceptions on the other methods.. which tends to indicate a poorly selected interface, but I'm offered no other choice. I know existing classes (ie Arrays) would have to continue to inherit from IList, but at least my own classes wouldn't have to and arrays and my own alike would all be compatible with methods expecting an IReadOnlyList (ie, a method that doesn't modify the list it's passed). Also I realise ICollection would have to be broken down similarly - but you know what? It should have been from the start =). (Sorry if double post)
@Alex: Problem with IReadOnlyList and a dervived IList is that if a bad guy have a reference to an IReadOnlyList, he can try to cast it to an IList. If he will success, you lose. You cannot avoid the readonly wrapper classes, if you want safe readonly collections.
Szindbad: The reason for having the IReadOnlyList interface isn't to prevent your list from being modified, it's for co/contra-variance. You want to be able to pass a List<Giraffe> to something expecting IReadOnlyList<Animal> or pass a List<Animal> to something expecting IExpandableWriteList<Giraffe>.
Trying to protect against bad guys like that whilst there's still reflection is mostly futile. I want it for co/contra-variance like Gabe says - but also because you often only have an IReadOnlyList. ie, look at the Enumerable.Repeat / Enumerable.Range - they currently return enumerables, losing the count information and making ToArray/ToList slower than necessary operators, making the idiom Enumerable.Repeat(0x55, numberOf55s).ToArray() unwise (20 times slower than a for loop). If they'd just implemented IReadOnlyList they could have attached the count to the returned results and this would become the recommended way of initialising an array to a value.
Possibly a bad example though - my most recent annoyance brought on by lack of IReadOnlyList has been on a popsicle-immutable BitVector class (similar to BitArray, just with a builder and a .MakeVector() method - I do a lot of bit operations talking to a device via RS232, this is very nice to have). It's just really annoying though that the immutable BitVector has to implement IList to really be usable - but to do that it has to throw on .Add(), .Clear(), .Remove(), .Insert(), .RemoveAt(), and this.Set. Even the builder - which is a fixed size once created (same as BitArray) needs to throw on .Add(), .Clear() (I could zero it, but lets be consistent with what IList.Clear() usually means), .Remove(), .RemoveAt(), and .Insert().
So I've got two classes, both of which implement IList, but both of which have to throw on what seems to be the majority of methods - but yet there is no better interface for me to implement. And then worst of all - whenever I pass one of these collections expecting IList, I know I'm not passing them a true IList - and their method could in theory throw an exception at any moment.
And then it's not only IList - imagine if there was an IReadOnlyCollection. All of Eric's immutability in C examples, the Deque, the Stack, the Queue, the AVLTree - add a count to each of those (yes it'll cost memory, but very useful to have) and they could all implement it, making ToArray/ToList extremely cheap, and allowing the Count to be retrieved via interface.
> Trying to protect against bad guys like that whilst there's still reflection is mostly futile.
Not in a sandbox, where visibility rules are enforced even for reflection (so you can't invoke a private member of another class etc).
That said, the problem here is that your interface name is a misnomer - IReadOnlyList implies that the list in question is read-only, but it's not true; the interface provided only allows read operations, but someone else may have a write interface to the same list and use it to update.
A more precise name would be IReadableList.
IReadOnlyList is indeed just a read-only interface to a list, but that's exactly what it says on the tin. If the list were immutable then it should've been called ImmutableList.
The established practice in .NET is that "read-only" has the same meaning as "immutable". To wit, the "readonly" modifier in C#, and ReadOnlyCollection<T> class in BCL. The contract for both is that no-one can mutate the data, not that only the particular user of the reference cannot.
Actually, my mistake - ReadOnlyCollection<T> is in fact a wrapper around a potentially mutable collection. So in fact the established practice is exactly the opposite of what I wrote, and IReadOnlyList would make perfect sense. My apologies for the mistake.
So, just now I'm modifying an internal class that takes two IEnumerables and stores them both in public readonly properties (with readonly backing fields). Now I'm modifying what action it performs on these IEnumerables, and it now requires that it accesses them out-of-order (rather than sequentially).
Now I know (internal class) that it's currently being created with List objects, so the logical solution is to change the constructor to accept two ILists, and modify the properties to be ILists too (this class is regularly recreated with the same lists, so this is required). Problem is - on creating the class, should I wrap the passed ILists in ReadOnlyCollections? Even though it's an internal class? Or do I just document that you must promise not to modify the properties?
Just trying to demonstrate the daily cases that working with ILists raises issues. IEnumerable is clear. You pass a constructor an IEnumerable, and you know it isn't going to go ahead and publish it on a public property as a mutable sequence, because it cannot. Pass a constructor an IList - and without good documentation you have no idea what it's going to do to it. You either need to defensively wrap it in a ReadOnlyCollection, make an assumption on what the constructor does with it, or start digging through the internals of that class to see what it does. So you decide to wrap it in a ReadOnlyCollection - only to discover that the class also defensively wraps it in a ReadOnlyCollection to prevent people from modifying the list through it's public properties. Double defensive, and for no gain as everyone's well-behaved using this internal class anyway.
It's not fun =(. IEnumerable is great.. but the very moment you need to index a passed collection it all falls in a heap.
Anyway, last post I'll make on this - I should have put it on SO anyway (as a "What do you do if you need to publish an IList as a public property" topic).