I had dinner with the BCL (Base Class Library) Team on Tuesday. Among those in attendance were Brad Abrams, Kit George, Joe Duffy and other framework developers. The ratio of Microsoft employees to non-Microsoft people was about 2:1.
I voiced a few concerns of mine:
Open API Specs.
I argued that Microsoft should release internal APIs specifications, because the MSDN documentation is poor. Although internal specs tend to be out-of-date and available only in English, they do provide more of the backstory of the API, that you typically find only in blogs or the few articles that appear on MSDN Magazine. MSDN documentation are written by the User Education group, who serve the needs of multiple products and are essentially out of the loop, while the specs are written by the same program managers who originate the features and work in close collaboration with testers and developers.
Releasing the specs may be less important for the BCL than for other groups, since sources are already available from Rotor; on the other hand, the BCL and CLR play a central part of every managed program.
My issues in past have been with GDI+ and System.Drawing, which is heavily underdocumented, and to a lesser extent, Windows Forms. Since System.Drawing wraps the unmanaged flat GDI+ API, the API is essential opaque. For example, it took me a while to learn how to overcome the limitations of GDI text rendering, that make it nearly unsuitable for developing a wordprocessor-like application. Microsoft had to issue a KB article that recommends either using GDI text support or enabling anti-aliasing, which produces blurry text for small font sizes, to overcome those limitations. Another example is the Save and BeginContainer methods in Graphics class, which perform very differently, yet have the same MSDN documentation that fails to differentiate between the two calls. Another example is the hoops that a number of smart developers had to go through to reverse engineer the Windows Forms designer and to create a new Designer surface.
Delegates
The CLR does not provide support for weak delegates, which leads to one of the most common sources of memory leaks in the framework. For example, the NumericUpDown control leaked memory because it failed to release an Application.Idle call after it was disposed. For my own projects, I have used weak interfaces in lieu of delegates.
I have seen two experts, a CLR developer, Joe Duffy, and a .NET author, Ian Griffiths, both screw up their implementations of weak delegates and in the exact same manner. What they both did was to create a weak reference that points to the delegate (rather than the target object of that delegate). Unless a reference to the delegate is saved elsewhere, the very next garbage collection will blow away the weak reference to the delegate regardless of whether the target of the delegate is reachable.
My other issue with delegates was the inability to change the target of a delegate. One could do this with reflection by calling MethodInfo.Invoke, but that is a couple orders of magnitude slower than it should be. Whidbey does provide a workaround with Lightweight Code Generation.
Miscellaneous
I requested support for weak collections, one of which includes a dictionary with a weak key. In this case, one cannot simply pass a weak reference as a key. Since I already have my own implementation, it wasn’t urgent for me.
I mentioned multiple dispatch methods—a kind of dynamic overloading. This is valuable for implementing the Visitor Pattern, a very powerful design pattern. I was surprised that people in the BCL were not well-versed in Design Patterns.
I also inquired about support for dynamic properties, which would allow some fields to be maintained in a dictionary to alleviate concerns with large number of fields or events.
I wish that I had brought up the ability to define methods within enumeration classes or to provide default implementations for interfaces.
I had a lot of radical ideas that I didn’t mention, mostly involving features from various academic languages that unlikely to come in the next few years. I firmly believe that the new advances in languages will borrow heavily from languages invented three decades ago such as Lisp and Smalltalk. Already, we have seen the advent of garbage collection, closures and iterators in C#. Languages will also become more declarative over time. (According to Alan Kay, computer professionals were smarter back then, because computing was still an esoteric technology. Now, we have a pop culture when colleges are essentially vocational schools for Java.)
I see you added a comment to my suggestion on the Product Feedback Centre (http://lab.msdn.microsoft.com/productfeedback/viewfeedback.aspx?feedbackid=8211e737-4086-4854-9611-a91354b06741).
Did you vote for it?
Posted by: Samuel Jack | March 24, 2005 at 05:34 AM
Hey Wesner, it was great chatting for a bit the other night. If you'd like to discuss further, just drop me a line at joedu at microsoft dot com.
Thanks for pointing out the (a?) flaw in my weak delegate implementation. Glad to see Ian made the same mistake. ;) I didn't spend enough time thinking through the whole thing, and am a little embarassed I made such a fundamental misstep. Ah well. As I noted, this is certainly a feature on our wish list for future versions. (The correct implementation, that is.)
Lazy or unbound delegates in Whidbey can be used to alter the target of the delegate per invocation. At least you could early in Whidbey. Now I'm not so sure. The IL I cooked up for this seemingly doesn't work properly on the latest drop. But I did read the spec, so I don't think I imagined it. I'm following up with JoelPob on this--it may be that reflection is the best you get for now. But I hope not.
Apologies for the double dispatch disconnect. I am certainly familiar with the visitor pattern, but just didn't hook up the terminology with the idea in that context. It's used quite a bit in all of my compilers--my standard backend uses a visitor with double dispatch for visiting nodes. I reuse visitors both for rewriting ASTs, annotating them with type inferencing information, and spitting out code. If you have specific questions around the topic, let me know.
I myself am quite interested in radical ideas, especially when having to do with academia (a little too much for my own good no doubt). Haskell is my true love, although there are plenty of other great language to learn from, too. I really wish we had better support for continuations, coroutines, baked in support for closures and access to free variables (rather than every compiler hacking it), a static notion of identifying side-effects versus pure computation, among many other "old" ideas. There are some really interesting new things on the horizon that I'm particularly interested in, too.
Take care.
Posted by: Joe Duffy | March 24, 2005 at 09:13 AM
well you said it tooks you a while to know the subtle difference between Graphics.Save() & Graphics.BeginContainer() or that it tooks you a while (too) to learn how to overcome the limitations of GDI text rendering.
Well, well, well...
but what about providing some links to those who have the same problem?
hey! ;)
Posted by: Lloyd Dupont | June 21, 2005 at 06:37 PM
Yes please do share what you learned about Graphics.Save vs Graphics.BeginContainer :)
Thanks in advance,
Posted by: Eric Cosky | March 16, 2006 at 08:39 PM
See post in http://wesnerm.blogs.com/net_undocumented/2006/06/msdn_wiki_post.html
Posted by: Wesner Moise | June 10, 2006 at 06:29 PM