Tuesday, August 10, 2010

Disoriented

The Tyranny of Terminology would have us discussing Object Orientation and Functional Programming, calling our code by its Patterns and Paradigms. I am going to plead ignorance of these epistemologies and just show you some C#. Feel free to know for yourself what it Really Means.

Code like this was written for Mono.Upnp. Expect news there soon.

Our story begins here:

abstract class ContentDirectory

"ContentDirectory" is UPnP parlance for a directory of content. (See the ContentDirectory:1 service template PDF. Or better still, don't.) The CD is a hierarchy of objects. Objects have descriptive class names like "object.item.audioItem.musicTrack" and "object.container.systemFolder". That gives you some idea, yes?

The CD has methods like Browse and Search. Here is the signature for Search:

string Search (string containerId,
               string searchCriteria,
               int startIndex,
               int requestCount,
               out int numberedReturned,
               out int totalMatches)


I will pause to explain the return value: it is a string of XML describing the result set.

Now, in a source file not far away...

class InMemoryContentDirectory : ContentDirectory

It may not shock you to learn that an InMemoryContentDirectory keeps an in-memory collection of its object hierarchy. It has a method called GetChildren. Here is the signature:

IEnumerable<CDObject> GetChildren (string containerId)

Explanatory pause #2: CDObject is short for "Content Directory Object"; it is the root type of objects in the CD.

If you were me, then this is how you would implement InMemoryContentDirectory.Search:

totalMatches = 0;
var results = new List<CDObject> (requestCount);
foreach (var child in GetChildren (containerId)) {
    if (IsMatch (child, searchCriteria)) {
        totalMatches++;
        if (totalMatches > startIndex &&
            results.Count < requestCount)
        {
            results.Add (child);
        }
    }
}
numberReturned = results.Count;
return Serialize (results);

I may or may not have promised a theory-free post — I don't really remember now — but in any event, this is standard Object Oriented Programing fare. To state the obvious:
  • You create a list to hold the results.
  • You iterate through the children of the subject container.
  • For each match, you increment totalMatches.
  • If you have not reached the startIndex, you keep going.
  • Otherwise unless you have reached the requestCount, you add the matching object to the results list.
  • You return the serialized results list.
    • Which iterates through the list and serializes each object to XML, returning the whole XML string.
I have highlighted the problems with your solution in salmon. You are allocating a new List<CDObject> to hold objects which already exist in a collection somewhere. Also, you are iterating through the results twice: first in your pass through the container's children and then again to serialize them.

If you were still me then this just won't do. LINQ should come to mind but have I got a fun surprise for you: Mono.Upnp targets the .NET 2.0 profile. So how might you Query the Language without fancy INtegration?

IEnumerable<CDObject> Search (
    string containerId,

    string searchCriteria,
    int startIndex,
    int requestCount)
{
    var count = 0;
    foreach (var child in GetChildren (containerId)) {
        if (IsMatch (child, searchCriteria)) {
            count++;
            if (count > startIndex &&
                count - startIndex < requestCount)
            {
                yield return child;
            }
        }
    }
}


string Search (string containerId,
               string searchCriteria,
               int startIndex,
               int requestCount,
               out int numberedReturned,
               out int totalMatches)

{
    var serializer = new Serializer ();
    var results = Search (
        containerId, searchCriteria,
        startIndex, requestCount);
    var xml = serializer.Serialize (results);
    numberReturned = serializer.NumberReturned;
    totalMatches = 0;
    return xml;
}
    No more List<CDObject> and we only iterate through the results once (during Serializer.Serialize). The serializer counts the results for us during its iteration and exposes Serializer.NumberReturned.

    There is one big problem: totalMatches will always be 0. We know what the correct value should be (it is the count variable in our generator), but we have no way to get it out: generator methods cannot have by-reference parameters (a.k.a. "out" parameters).

    To make this solution work, we could return something fancier than plain old IEnumerable<CDObject> which would expose count through a property; let's call it TotalMatchesCount. But we could not use generators; we would have to implement IEnumerator<CDObject> by hand just like'n Ye Olde Days.

    A final caveat: TotalMatchesCount would only have the correct value after we iterate through the results in Serializer.Serialize, just as with Serializer.NumberReturned.

    This approach frankly sucks. Alright you/me, show me your teeth!

    abstract void VisitChildren (string containerId,
                                 Action<CDObject> visitor);

    string Search (string containerId,
                   string searchCriteria,
                   int startIndex,
                   int requestCount,
                   out int numberedReturned,
                   out int totalMatches)
    {
        var total = 0;
        var count = 0;
        var serializer = new Serializer ();
        VisitChildren (containerId, child => {
            if (IsMatch (child, searchCriteria) {
                total++;
                if (total > startingIndex &&
                    count < requestCount)
                {
                    serializer.OnResult (child);
                    count++;
                }
            }
        });
        numberReturned = count;
        totalMatches = total;
        return serializer.OnDone ();
    }

    No more IEnumerable<CDObject> GetChildren, and the implementation lives in the abstract ContentDirectory class where it works with any sort of subclass: in-memory, db-backed, web service, &c.

    As an exercise I want you to invent a name for this pattern which rhymes with neither "shmisitor" nor "shmobserver." Bonus points for double entendres. Then I want you to imagine a world without return values. Get back to me when your mind is blown.

    Tuesday, July 28, 2009

    Mono.Upnp Dance Party

    So it's been a while since mention was made of a certain UPnP library. What happened? First, I had various other things to do. Second, I decided to do two or three major refactorings, ditching a lot of code. Third, I moved development to github.

    What the status?
    The status? The status, you ask?! THIS is the status! If you can't see, I am pointing at my TV. My TV which is connected to my PS3. My PS3 which is playing music from my laptop computer with WIRELESS NETWORKING! Yes friends, tonight at last, Mono.Upnp and the PS3 are doing the DANCE OF LOVE. I plug, it plays. Universally. About ten minutes ago I finally tracked down the typo responsible for a day's worth of debugging and let me tell you, Starfucker never sounded so good (and they already sound so good anyway, seriously, you should listen to them).

    What now?
    I've kept pretty quite about the whole project because I wanted to lay all the groundwork before make too much noise. There is still work to be done on the core of the library, but now that it's working I'll start sharing more frequent updates. You can follow the project on github if you want commit-by-commit news.

    Can I help?
    Sure! But helping might be a little tricky. The solution only loads in MonoDevelop SVN, and there are certain necessary BCL fixes that require Mono from SVN too (one of them isn't even committed yet). It's not quite "checkout, compile, run," but if you're interested in helping out, I will be more than happy to get you up to speed. I wrote a TODO on the github wiki today with some stuff that needs doing. Testing is also something I will need help on. I don't have access to an XBox 360 anymore, so I'm going to need help on that front. As the library and the tools evolve, we'll need to test with as many devices as we can.

    Yeah!
    Yeah indeed! NOW DANCE!

    Thursday, July 23, 2009

    C#er

    Was chillin' with the impish abock last weekend when, all of a hullabaloo, he geniused something wonderful.

    "Behold!" he cried:

    var button = new Button {
        Label = "Push Me",
        Relief = ReliefStyle.None
    };
    button.Clicked += (o, a) => Console.WriteLine ("ouch!');


    To which I replied, "?"

    "Watch..." said he:

    var button = new Button {
        Label = "Push Me",
        Relief = ReliefStyle.None,
        Clicked +=> Console.WriteLine ("ouch!")
    };


    "?!" came my response.

    "Is not it better?"

    "Yes," quoth I, "but gentle abock, this wundercode... it doth not compile!"

    "... YET!"

    Well friends, yet is over. I am here today to tell you that yes, IT DOTH COMPILE. This is what you get when Scott forgets to pull the git repos for his real projects before a plane flight: unsolicited language features. And there are other goodies:

    As with anonymous methods via the delegate keyword, you may omit the parameters to a lambda if you aren't going to use them. This is also helpful when the delegate type has no parameters. For example:

    Func<string> myFunc = () => "blarg";


    Just look at those parenthesis! Chillin' there all higgledy piggledy. They look like some unseemly ASCII art. But now, presto chango:

    Func<string> myFunc => "blarg";


    See what I did there? That's called an assignment arrow. It is better. Don't argue with me, because you're wrong.

    For my next trick, you can do the same kind of thing with lambdas and event handler registration.

    myButton.Clicked +=> Console.WriteLine ("higgledy piggledy");


    Because who ever uses the EventHandler arguments? A big, fat nobody, that's who.

    Last but not least, you can now do all of this plus regular event handler registration inside of object initializers. abocks around the world rejoice!

    There Is No Syntax Without Corner Cases


    So there is at least one possible ambiguity with this new syntax:

    class Foo {
        public void Add (Action<string> action) { ... }
        public Action<string> Bar { get; set; }
    }

    // Meanwhile, in some unsuspecting method:
    var foo = new Foo {
        Bar => Console.WriteLine ("HELP ME!")
    };


    Question: Is that an object initialization, or a collection initialization?

    Answer: It's ambiguous.

    Solution: It's an object initialization. If you want it to be a collection initialization, throw some parenthesis around "Bar." This would be a good candidate for a compiler warning. And if you want to make it an unambiguous object initialization, you could do:

    var foo = new Foo {
        Bar = () => Console.WriteLine (
            "What does this ASCII art even mean?")
    };


    Patch


    The patch for all of this is available here. Apply to mcs, recompile, then use gmcs.exe passing -langversion:future.

    Future


    There has been on-again-off-again talk about adding non-standard language features to the C# compiler under the guard of -langversion:future. The main concern voiced is the ability to maintain such extensions. I will definitely discuss this patch with Marek and co. to see about landing it in mainline. I'll keep you up to date.

    Are You Bock Enough?


    In the meantime, I call upon manly man Aaron Bockover to make the only manly choice available: fork C# and ship the compiler. Because you're not really a serious media player until you have your own special language.

    Thursday, July 16, 2009

    Casting Call

    Type safety only gets you so far; eventually you have to cast. There are three features in the C# language which address typing: the unary cast operator and the binary "as" and "is" operators. I see people misuse these operators all the time, so here for your records are the official Best Ways to use each.

    If you want to check the type of an object and do not care about using the object as that type, use the "is" operator. For example:

    if (thing is MyType) {
        // do something which doesn't involve thing
    }

    If you want to check the type of an object and then use that object as that type, use the "as" operator and the check for null. For example:

    var my_type_thing = thing as MyType;
    if (my_type_thing != null) {
        // do something with my_type_thing
    }

    This only works for reference types since value types cannot be null. For value types, use the "is" and cast operators. For example:

    if (thing is MyValueType) {
        var my_value_type_thing = (MyValueType)thing;
        // do something with my_value_type_thing
    }

    If you know for a fact that an object is some type, use the cast operator. For example:

    var my_type_thing = (MyType)thing;
    // do something with my_type_thing

    These patterns minimize the operations performed by the runtime. This wisdom comes by way Marek who educated me on this a while ago. Please pass it on.

    Thursday, July 9, 2009

    Dear LazyMarket

    Are you hiring? Do you know someone who is hiring? Well you're in luck! Because none other than yours truly is looking for a job. If you're interested in how great I am, send an email to lunchtimemama@gmail.com and I'll get you a copy of my resume. I look forward to hearing from you...

    Tuesday, June 30, 2009

    Variance, Thy Name is Ambiguity

    Previously
    On This Blog...

    "I love you, Generic Variance, and I want your babies RIGHT NOW!"

    "I think there's something you should know about Generic Variance..."

    "I can change him!"


    And now, the thrilling continuation...

    I've just sent my recommendation to the ECMA 335 committee regarding the generic variance problem. I present it here for your reading pleasure:


    Quick Recap


    The following is an example of an ambiguous circumstance involving generic variance, the very sort over which we have all lost so much sleep:

    .class interface abstract I<+T> {
        .method public abstract virtual instance !T Foo ()
    }

    .class A {}
    .class B extends A {}
    .class C extends A {}

    .class X implements I<class B>, I<class C> {
        .method virtual instance class B I[B].Foo () { .override I<class B>::Foo }
        .method virtual instance class C I[C].Foo () { .override I<class C>::Foo }
    }

    // Meanwhile, in some unsuspecting method...
    I<A> i = new X ();
    A a = i.Foo (); // AMBIGUITY!


    Give a Runtime A Bone


    To disambiguate such situations, we introduce a new custom attribute in the BCL. For the sake of example, let's call it System.PreferredImplementationAttribute. The PreferredImplementationAttribute is applied to a type and indicates which implementation should be selected by the runtime to resolve variance ambiguities. Our above definition of the type X would now look like this:

    .class X implements I<class B>, I<class C> {
        .custom instance void System.PreferredImplementationAttribute::.ctor (class System.Type) = { type(I<class C>) }
        .method virtual instance class B I[B].Foo () { .override I<class B>::Foo }
        .method virtual instance class C I[C].Foo () { .override I<class C>::Foo }
    }


    New Rules


    With the addition of this attribute, the runtime requires that any type defined in an assembly targeting the 335 5th edition runtime which implements multiple interfaces that are variants of a common generic interface MUST specify ONE AND ONLY ONE PerferredImplementationAttribute for EACH of the potentially ambiguous common interfaces, and that each such specification of a PerferredImplementationAttribute must reference an interface implemented by the type that is a legal variant of the ambiguous common interface. In other words, all possible ambiguities MUST be disambiguated by the use of PreferredImplementationAttribute custom attributes. If a type does not satisfy these rules, the runtime MUST throw a System.TypeLoadException.

    As this rule only applies to assemblies targeting the new version of the runtime, old images will continue to execute without issue. If the committee prefers, the resolution of ambiguities in old types may remain unspecified, or alphabetical priority could be codified in the spec to standardize such behavior. I would be fine leaving it unspecified.


    Custom Attributes vs. Metadata


    Ideally, I feel disambiguation information belongs in the type metadata structure rather than a custom attribute. If the committee feels that amending the metadata specification is tenable, I would recommend doing so (though I don't have any thoughts at this time on the exact logical or physical nature of such an amendment). If, on the other hand, changing the metadata spec at this point in the game is not feasible, then a custom attribute will just have to do. I see the addition of one custom attribute type to the Base Class Library as entirely justified.


    An Aside to Our Friends on the 334 Committee


    As a note to language designers targeting the runtime, I personally would consider it obnoxious if developers where burdened with the manual application of such a custom attribute. C# and other languages would do well to prohibit the direct use of the custom attribute, favoring instead a special syntax to denote the preferred implementation (the "default" keyword comes to mind in the case of C#). If this committee changes the type metadata spec to include preferred implementation information (and does not introduce a custom attribute type for that purpose), then special language syntaxes will be necessary.


    An Alternative


    In the interest of completeness, I will describe an alternate (if similar) approach to the ambiguity resolution problem. Rather than annotate types to indicate which of their interface implementations will satisfy ambiguous calls, the preferred implementation could be denoted on a per-member basis. Referring again to our original type X, this solution would modify that type thusly:

    .class X implements I<class B>, I<class C> {
        .method virtual instance class B I[B].Foo () { .override I<class B>::Foo }
        .method virtual instance class C I[C].Foo () {
            .override I<class C>::Foo
            .custom instance void System.PreferredImplementationAttribute::.ctor ()
        }
    }

    The member I[C].Foo is annotated with the System.PreferredImplementationAttribute, indicating that it will be selected by the runtime to fulfill otherwise ambiguous calls to I<T>.Foo. Note that in this solution the constructor to the PerferredImplementationAttribute type is parameterless. The runtime ensures that for EACH of the members of an interface which is the common variant of two or more of the interfaces implemented by a type, ONE AND ONLY ONE of the implementations for that member is flagged as "preferred."

    Per-member preference definition affords developers more control but costs runtime implementers time, effort, and simplicity. I also don't envision many scenarios when developers would desire per-member control over implementation preference. I personally find this approach less tasteful than the per-interface solution but I mention it here, as I said, for completeness.


    One More Thing...


    There remains a situation on which there are varied opinions:

    .class interface abstract I<+T> {
        .method public abstract virtual instance !T Foo ()
    }

    .class A {}
    .class B extends A {}

    .class X implements I<class A> {
        .method virtual instance class A I[A].Foo () { .override I<class A>::Foo }
    }

    .class Y extends X implements I<class B> {
        .method virtual instance class B I[B].Foo () { .override I<class B>::Foo }
    }

    // Meanwhile, in some unsuspecting method...
    I<A> i = new Y ();
    A a = i.Foo ();

    In this situation I<A>::Foo is called on an object of type Y. There is an implementation of I<A>::Foo in Y's type hierarchy (X::I[A].Foo), but there is also an available implementation which is a legal variant of I<A> in Y itself (Y:I[B].Foo). Does the runtime favor the exact implementation, or the more derived variant implementation? I don't have strong feelings on the matter, but my slight preference is for favoring the exact implementation.

    The runtime is deciding on behalf of the developer which implementation is most appropriate. It could be argued that an exact implementation, wherever it is to be found the type hierarchy, is more appropriate than a variant implementation.

    Also - and this is an implementation detail which should not outweigh other considerations but may be useful to keep in mind if all other things are equal - Mono stores a type's implemented interfaces in a binary tree, meaning that finding an exact implementation is an O(log n) worst-case operation, whereas finding a legal variant interface among a type's implemented interfaces is an O(n) worst-case operation (all interfaces must be examined to see if a legal variant exists among them). I haven't heard of any way to do O(log n) (or better) lookup of variants. With such popular types as IEnumerable`1 becoming variant, the superior time complexity could make a difference.

    Saturday, May 16, 2009

    Further Generic Variance Thoughts

    I was writing a type today that implements both IDictionary<TKey, TValue> and ICollection<TValue>. These interfaces require the implementation of both IEnumerable<TValue> and IEnumerable<KeyValuePair<TKey, TValue>>. In .NET 4, the IEnumerable<T> type will be covariant. This exposes my type to potential ambiguity if it is assigned to a location of type IEnumerable<object> (see the previous post for details). If I were to follow my own advice and forbid the implementation of multiple interfaces which are variants of a single common interface, this type would be illegal. So on further reflection, I have decided to amend my opinion thusly: If there are multiple interface implementations which are variants of a common interface, then there must be implicit implementations of all of the potentially ambiguous members. These public members are then selected by the runtime to satisfy otherwise ambiguous calls. The implicit member implementations need not all be for the same interface. For example, if we have some interface IFoo<out T> with members T Bar(); and T Bat(); and we have some type with implements both IFoo<string> and IFoo<Uri>, it could have the members public string Bar(){} and public Uri Bat(){}. Any call to IFoo<object>.Bar() on an object of this type will execute the IFoo<string> implementation, and IFoo<object>.Bat() will execute the Uri implementation.

    I believe that this restriction should be enforced at least at the language level (for all variant-capable languages targeting .NET), if not at the runtime level: all potentially ambiguous members must have public implementations. This resolves the ambiguity in a logical way, allows for more complex type design (which, as in the case of my type today, is desirable), and gives developers the ability to control which implementation will be selected. I think it is a Good Thing.

    Thursday, April 9, 2009

    Who's Afraid of Generic Variance?

    Abstract


    This post is an in-depth exploration of generic variance in the ECMA 335 standard and the REALLY BIG PROBLEM therewith. See the previous post on generic variance for an introduction to the topic.


    The Punchline


    The ECMA 335 Standard, 4th Edition, allows for nondeterministic execution. This means that in certain situations involving generic variance, the specification does not provide sufficient guidance to resolve ambiguities. As you may imagine, nondeterminism is a Very Bad Thing in computing (usually). It means that your program may run one way on .NET 3.5 and another way on .NET 4 and a third way if Richard Stallman saw his shadow in the morning.


    The Solution


    The ECMA 335 committee is hoping to resolve this problem in the 5th edition. Unfortunately, no clear solutions have revealed themselves. There are a number of possible approaches, all of which have pros and cons. I will be describing the problems and their possible solutions in this post. Feel free to weigh in on the matter. A robust discussion will aid the 335 group in their decision.


    The Implementation Selection Problem


    There are a number of increasingly pointy corner cases, all variations on the same theme: which of multiple implementation does the runtime select for execution? I will describe these corner cases in order of ascending pointiness. For each case, I will propose a deterministic solution and then demonstrate how that solution fails to address the next corner case. (Note: the deterministic solutions I propose are merely examples. Other solutions could be used.)


    Overview


    Before getting into the corner cases, I will provide a broad overview of the problem. Ambiguous situations arise when there are multiple implementations of one generic interface (with different type arguments). The generic interface must have some variant generic type parameter.

    Vocab

    The implemented types are the closed generic interface types that are actually implemented in the type hierarchy of the object in question.

    The execution type is the closed generic interface type of the location to which the object is assigned. Calls made to members of this type must be resolved to an implementation among the implemented types.

    An exact implementation is the implementation of an implemented type whose generic type arguments precisely match those of the execution type. For example, if type A implements the generic interface I<String>, and we assign some A to an I<String> location, then its implementation for that interface is exact.

    A variant implementation is the implementation of an implemented type whose generic type arguments do not precisely match those of the execution type, but are legal variants thereof. For example, if type A implements the covariant generic interface I<String>, and we assign some A to an I<Object> location, then its implementation for that interface is variant.


    Case 0

    Nothing to See Here

    As a starting point, let us consider the following non-variant scenario which is NOT ambiguous.

    interface I<T> {
        T Next();
    }

    class A {}

    class X : I<A> {
        A I<A>.Next() {...}
    }

    class Y : X, I<A> {
        A I<A>.Next() {...}
    }

    // Test code
    I<A> i = new Y();
    A someA = i.Next();

    Problem
    There are two implementations of I<A>: one in X and one in Y. Which is used for the call to I<A>.Next()?

    Solution
    The implementation in type Y is used. As I said, this is not actually a problematic situation. I illustrate this case to demonstrate one of the ways the spec currently resolves potential ambiguities. In this case, the implementation in the most derived class is used. Y is more derived than X, therefore its implementation is used.


    Case 1

    Easy Pickins

    interface I<out T> {
        T Next();
    }

    class A {}

    class B : A {}

    class X : I<A> {
        A I<A>.Next() {...}
    }

    class Y : X, I<B> {
        B I<B>.Next() {...}
    }

    // Test code
    I<A> i = new Y();
    A someA = i.Next();

    Problem
    There are two implementations which suffice for I<A>: the I<A> exact implementation in X, and the I<B> variant implementation in Y. Which does the runtime select?

    Solution
    There are two possible solutions. We could adopt the aforementioned "most derived implementation wins" rule, in which case the runtime would pick the variant implementation in Y.

    The other solution is to favor exact implementations over variant implementations, in which case the runtime would pick the exact but less derived implementation in X.

    For the sake of argument, let's adopt the second solution: the runtime will select the most-derived exact implementation if one exists.


    Case 2

    The Decider

    interface I<out T> {
        T Next();
    }

    class A {}

    class B : A {}

    class C : B {}

    class X : I<B> {
        B I<B>.Next();
    }

    class Y : I<C> {
        C I<C>.Next();
    }

    // Test code
    I<A> i = new Y();

    Problem
    There is no exact implementation of I<A>. There are two variant implementations: I<B> in X and I<C> in Y. Which does the runtime select?

    Solution
    As before, there are two options. We could choose the most derived implementation, in which case the runtime would select the I<C> implementation in Y.

    The other option is to select the variant implementation with the least "distance" to the execution type. We are attempting to select an implementation for I<A>. We have variant implementations I<B> and I<C>. B is nearer to A in the inheritance chain than is C. Therefore we say that I<B> has less "distance" to I<A> than does I<C>. It may therefore be the case that the I<B> implementation is a more relevant substitute for I<A> since B is nearer to A than is C. By this rule, we would select the less distant but less derived I<B> implementation in X.

    There are problems with the second option. What if there are multiple type parameters, each with different distances? How do we calculate the total distance of the type? Such a solution could require a rather complex set of rules, complicating the specification and compliant runtimes. And at the end of the day, it is dubious whether "distance" is a meaningful selection criteria.

    For the sake of argument, let us go with the first option: the runtime will select the most derived variant implementation in the absence of an exact implementation.


    Case 3

    Ambiguity is Scary

    interface I<out T> {
        T Next();
    }

    class A {}

    class B : A {}

    class C : B {}

    class X : I<B>, I<C> {
        B I<B>.Next () {...}
        C I<C>.Next() {...}
    }

    // Test code
    I<A> i = new X();
    A someA = i.Next();

    Problem
    There is no exact implementation for I<A> and there are two variant implementations, I<B> and I<C>, both defined in the same type: X. Which does the runtime select?

    Solution
    We are now approaching the point at which any selection rule is largely arbitrary. We can revisit the "least distant" option though its problems are no fewer. It is also unclear whether such a selection behavior is obvious to the user. The user may not have taken "distance" into consideration when designing their types. On the other hand, the user who wrote this code clearly failed to take a number of things into consideration and it's now the runtime's job to make the best possible choice. Anything is better than nondeterminism.

    For the sake of argument, let us say that we select the variant implementation with the least distant type argument. If there are multiple type parameters, we take the distance from the first non-identical set of arguments.


    Case 4

    Sophie's Choice

    interface I<out T> {
        T Next();
    }

    class A {}

    class B : A {}

    class C : A {}

    class X : I<B>, I<C> {
        B I<B>.Next() {...}
        C I<C>.Next() {...}
    }

    // Test code
    I<A> i = new X();
    A someA = i.Next();

    Problem
    There is no exact implementation of I<A>. There are two variant implementations: I<B> and I<C>, both defined in type X. B and C are equidistant from A. What would Jesus do?

    Solution
    Select I<B>. Because B comes before C in the alphabet.

    If you think that's heinously arbitrary, you're right! But remember our motto: anything is better than nondeterminism.

    [UPDATE]
    Several people have proposed selecting based on the order in which the implementations appear in the code. This would select I<B> because it is defined first. As I said, my solutions are merely example rules.


    Recap


    To review, our selection rules are:
    1. The most derived exact implementation wins

    2. Failing an exact implementation, the most derived variant implementation wins

    3. If there are multiple equally-derived variant implementations and no exact implementation, the implementation with the least "distance" wins. If there are multiple type parameters, the distance is taken from the first non-identical set of arguments.

    4. If there are multiple equally-derived equidistant variant implementations and no exact implementation, the implementation with alphabetical priority wins. If there are multiple type parameters, the alphabetical priority is taken from the first non-identical set of arguments.



    How Arbitrary Is Too Arbitrary?


    As the cases get cornerier, the solutions get arbitrarier. Somewhere around case 3, the arbitrariness begins to offend the delicate sensibilities. There are alternatives to arbitrary selection which I will describe in a moment but I would like to first emphasize the virtue of arbitrariness: it is better than nondeterminism. ANYTHING is better than nondeterminism. Eeny meeny miny moe is a step up from the current spec. If no other solution can be decided upon, egregious arbitrariness is still better than what we have.

    As we consider alternatives to arbitrary selection, consider the question, "how arbitrary is too arbitrary?" For which of the above cases is one of the below alternatives a superior option? Bear it in mind as we press ahead...


    Exceptions


    Runtime exceptions are an alternative to arbitrary implementation selection. If an ambiguous situation arises, an exception pops up. The benefit of exceptions is that they let the developer know that there is an ambiguous situation, whereas arbitrary selection may simply lead to unexpected and difficult-to-debug behavior. There are two exceptional approaches:

    Exception On Call

    When an ambiguous call is made, throw a runtime exception. For example:

    interface I<out T> {
        T Next();
    }

    class A {}

    class B : A {}

    class C : A {}

    class X : I<B>, I<C> {
        B I<B>.Next();
        C I<C>.Next();
    }

    // Test code

    I<A> i = new X();
    A someA = i.Next(); // AMBIGUOUS CALL EXCEPTION HAPPENS HERE

    This has the benefit of only throwing an exception if the ambiguity is actually going to be a problem. The major issue is, exceptions can be thrown from innocent code. If you pass an X to some library function which takes an I<A>, that library will blissfully call I<A>.Next() and trigger the exception. The stack trace will implicate the library, but the culprit is the X type definition.

    Exception On Assignment

    When an object is assigned to an ambiguous interface, throw a runtime exception. For example:

    interface I<out T> {
        T Next();
    }

    class A {}

    class B : A {}

    class C : A {}

    class X : I<B>, I<C> {
        B I<B>.Next();
        C I<C>.Next();
    }

    // Test code
    I<A> i = new X(); // AMBIGUOUS ASSIGNMENT EXCEPTION HAPPENS HERE
    A someA = i.Next();

    This approach runs the risk of unnecessary exceptions. If an ambiguous call is never made, an ambiguous assignment is not dangerous. This approach also allows exceptions to be thrown from innocent code. If some library takes an I<B>, an X can be passed without ambiguity. The library is then at liberty to assign the I<B> to an I<A>, resulting in an exception. The library is not at fault, but the stack trace implies otherwise.


    Invalid Ambiguity


    Once you have answered the question "how arbitrary is too arbitrary," take everything on the "too arbitrary" side of the fence and make it against the rules. For example, if you conclude that there is no reasonable way of selecting between two variant implementations defined in the same type, then it would be invalid to define a type which implements multiple interfaces that are variants of a common interface.

    This has the downside of invaliding currently valid CLI images. I don't know to what degree forward compatibility is a goal for the ECMA 335 spec.


    Language-Level Enforcement


    Irrespective of the runtime's solution to this problem, languages can impose independent restrictions on ambiguous type design. For example, C# could make it a compilation error for a type to implement multiple interfaces that are variants of a common interface, even if such a type is valid for the runtime. If all major languages enforce unambiguous type design, the pressure on the runtime to avoid arbitrariness is lessened since the dangerously arbitrary rules will not affect any code written in a major language. The only people vulnerable to the arbitrary rules are ostensibly savvy enough to be trusted with understanding obscure runtime behaviors.


    The Least Worst Solution


    There is clearly no silver bullet for the problem. The least worst solution will be a blend of several approaches. The appropriate blend will depend upon a number of things such as the importance of the forward compatibility of CLI images. The ultimate solution must address two concerns: the elimination of nondeterminism and the prevention of developer confusion. The same implementation must deterministically execute every time, and it must be clear to developers which implementation that will be.


    My Thoughts


    The implementation selections rules should begin as follows:
    1. The most derived exact implementation wins.

    2. In the absence of an exact implementation, the most derived variant implementation wins.

    Situations not addressed by these rules are considered "ambiguous."

    As a solution to ambiguous situations, exceptions serve neither of the stated goals. They achieve deterministic failure rather than deterministic execution and their stack traces obfuscate the root of the problem. A sufficiently descriptive error message could aid developer comprehension but it would be far too easy for a stack trace from "someone else's code" to become a bug report to the wrong people or an ignored problem. I think exceptions are the worst worst solution.

    Language-level ambiguity preclusion is an very good idea but adding a compiler error for ambiguous type design could break existing code when existing interfaces are made variant. For example, consider this C#:

    class A {}

    class B : A {}

    class C : A {}

    class X : IEnumerable<B>, IEnumerable<C> {...}

    This is currently a legal C# class definition. However with the release of .NET 4 the IEnumerable<T> interface will be made covariant, making the above class vulnerable to ambiguity. Making ambiguous type design a warning rather than an error would solve this problem but I think it is worth breaking existing code in the interest of drawing developers' attention to the new ambiguity.

    All variance-capable .NET languages should add errors for ambiguous type design.

    Which brings us to the question of the runtime's ambiguity handling mechanism. The two best options are:
    1. Make ambiguities illegal.

    2. Add an arbitrary implementation selection rule: alphabetical priority of type arguments.

    Option 1 achieves both objectives of a solution: it guarantees deterministic execution and ensures developer comprehension by proscribing ambiguous circumstances altogether. However it also breaks the forward compatibility of existing binaries.

    Option 2 guarantees deterministic execution but does not serve developer comprehension (no developer wants to consider the alphabetical priority of type arguments when designing their types). In conjunction with language-level enforcement, however, no developer should ever suffer this confusion. And this option affords all currently valid CLI images continued validity.

    So the key question is, how important is compatibility?

    I am tending toward option 1, but I think there is room for debate.


    What Do You Think?


    Comment away.


    Next Time...


    If all that weren't enough, there is a problem with variancifying existing types (such as turning IEnumerable<T> into IEnumerable<out T>) but I will save that for another post.


    Thanks


    Thanks goes to Dr. Nigel Perry on the ECMA 334 and 335 standards committee for working with me on this.

    Saturday, April 4, 2009

    Exceptional APIs

    Axioms for public API design:

    Axiom 1
    NullReferenceExceptions that come out of your code ARE YOUR FAULT!

    Axiom 2
    The fewer exceptions your code can possibly throw, the better!

    Applications of these axioms:

    Let's say we're writing a public API, you and I. In it, let's say we have the following awesome method:
    public void Foo(string s) {
        Bar(s.Length);
    }
    You will notice that we dereference s to get its Length property. If some misguided user of ours were to pass null to Foo, an NRE would pop out of our code like an overweight stripper out of a wedding cake. Awkward! And then the stack trace would get passed all over school and all the kids would laugh at us.

    Lemma 1
    From axiom 1 it follows: Null-check EVERYTHING YOU DEREFERENCE unless you know where it came from.

    We could do a conditional dereference:
    public void Foo(string s) {
        if (s != null) Bar(s.Length);
    }
    Or we could verify the argument:
    public void Foo(string s) {
        if (s == null) throw new ArgumentNullException("s");
        Bar(s.Length);
    }
    If our method absolutely needs to dereference the object in order to do its job, then argument verification is the way to go. This may seem like trading one exception type for another, but it's really not. Argument exception types are perfectly acceptable - they inform our misguided user what went wrong and how to make it right. On the other hand, NREs mean that we didn't verify the argument or null-check before dereferencing. And they mean that all the kids will laugh at us.

    Let's say that we decide on argument verification. Now let's say that we want to add a convenience overload:
    public void Foo() {
        Foo("");
    }
    Looks good, right? WRONG!

    Lemma 2
    From axiom 2 it follows: Use 'null' as a sentinel between overloads for the default value when null is not an otherwise permissible value.

    My favorite non-fiction book of all time, Framework Design Guidelines, specifically says not to do this. It is wrong. Well, sort of. FDG advises against using null as a "magic" sentinel, period. I argue that sentinel null is correct for parameters which are omitted in convenience overloads. Here is why:

    To recap, our API currently looks like this:
    public void Foo() {
       Foo("");
    }

    public void Foo(string s) {
        if (s == null) throw new ArgumentNullException("s");
        Bar(s.Length);
    }
    Let's consider the possible ways our misguided user can use this API. If he or she calls the convenience overload, or passes a string literal, everything's honkey dorey:
    Foo(); // This is fine
    Foo("How the hell do I use this API?"); // This too is just fine

    But if misguided user passes null to Foo(string), or passes a variable which may be null, things aren't so rosey:
    Foo(null); // Exception city!
    Foo(someString); // It depends...

    How is our misguided user to know what is and is not a safe call? They could look at our documentation. Assuming we wrote any. And assuming we correctly documented all of the parameters which need to be non-null. Or they could test passing null and see if it throws.

    (As a side note, I wonder all the time about whether I can pass null to an API. Documentation is usually no help and if I see a parameterless overload, I generally assume that I can)

    More likely, they will do none of the above and just write something resembling the last example call, passing a variable. A variable which is usually not null. A variable which is never null during testing. But a variable which, when released into the wild may, under some unforeseen circumstance, be null. Then all the kids would cry.

    The solution:
    public void Foo() {
        Foo(null);
    }

    public void Foo(string s) {
        if (s == null) s = "";
        Bar(s.Length);
    }
    All possible inputs to this API are valid and there is zero change of an exception. This is better!

    Some may complain about semantics purity or somesuch. They are wrong.

    So, if you have some public API which takes a parameter that a) is not allowed to be null, and b) has a default value for the purpose of convenience overloads, use the sentinel null. Just do it.

    Sunday, February 22, 2009

    Now Is The Winter of Our Optional and Named Parameters

    Optional and named method parameters are coming to C# 4. This means you can provide default values for method parameters. When you call the method, you can name only the parameters you want to specify - default values will be used for all other parameters.

    Here's how you use it:

    public void Foo (
        int doodad = 1,
        string humdinger = "",
        string wuchacallit = "STELLAAAA!")
    {
        // Do stuff here
    }

    void Test ()
    {
        Foo ();
        Foo (humdinger = "Beard Lust");
        Foo (doodad = 5,
             wuchacallit = "SHAMU!");
        Foo (wuchacallit = "Kia",
             humdinger = "Ora",
             doodad = 42);
    }

    Here's how it really works:

    public void Foo (
        [Optional, DefaultParameterValue(1)]
        int doodad,
        [Optional, DefaultParameterValue("")]
        string humdinger,
        [Optional, DefaultParameterValue("STELLAAAA!")]
        string wuchacallit)
    {
        // Do stuff here
    }

    void Test ()
    {
        Foo (1, "", "STELLAAAA!");
        Foo (1, "Beard Lust", "STELLAAAA!");
        Foo (5, "", "SHAMU!");
        Foo (42, "Ora", "Kia");
    }


    The compiler just sprinkles the default values into every callsite. There are a few problems with this approach. Let's suppose I release version 1 of my awesome library with the above Foo method. You compile. All is well. Now let's say I release version 2 of my library, in which the default value "STELLAAAA!" is changed to "KHAAAAN!". But your code still has the old default value baked in. You need to re-compile your code to get the new default value. There is also the problem that injecting the full argument list into every callsite bloats the size of the code. Bigger code means more to JIT and fewer cache hits

    How it should work:

    struct FooSettings {
        int doodad_value = 1;
        string humdinger_value = "";
        string wuchacallit_value = "STELLAAAA!";

        public int doodad {
            get { return doodad_value; }
            set { doodad_value = value; }
        }
        public string humdinger {
            get { return humdinger_value; }
            set { humdinger_value = value; }
        }
        public string wuchacallit {
            get { return wuchacallit_value; }
            set { wuchacallit_value = value; }
        }
    }

    public void Foo (FooSettings settings)
    {
        // Do stuff
    }

    void Test ()
    {
        Foo (new FooSettings ());
        Foo (new FooSettings { humdinger = "Beard Lust" });
        Foo (new FooSettings {
            doodad = 5,
            wuchacallit = "SHAMU!" });
        Foo (new FooSettings {
            wuchacallit = "Kia",
            humdinger = "Ora",
            doodad = 42 });
    }


    Thanks to C# 3's object initialization, you can squint at the call and almost see the named parameter syntax (just ignore "new FooSettings"). This pattern of using a special "settings" type for passing arguments to methods already exists in the framework (see XmlReader.Create and XmlWriter.Create for an example). I am proposing that the compiler auto-generate these types and provide full optional/named parameter sugar. The compiler-generated types would be publicly nested within the type containing the method and named "[MemberName]Settings" by default.

    This is better than callsite default value injection because:
    • It versions well

    • It adds a fixed amount of additional code (the type), whereas injection adds more code every time you use it

    • It is CLS compliant

    This is how C# 4 should do optional and named parameters.

    Saturday, February 14, 2009

    Generic Type Parameters AS Method Parameters

    I have long had an interest in method contracts (pre- and post-conditions). I followed Spec# and I continue to follow the Pex project. I am also a big fan of doing argument verification at the highest possible level of a public API. I was working on a public API today which takes a Type object. My method looked like this:

    public string GetClassName (Type type) {
        if (type == null) {
            throw new ArugmentNullException ("type");
        }

        if (!type.IsSubclassOf (typeof (UpnpObject)) &&
            type != typeof (UpnpObject)) {
            throw new ArgumentException (
                "The type does not derive from UpnpObject.",
                "type");
        }

        // do stuff with 'type'
    }


    It then occurred to me that I can do the same thing with a generic type parameter, but get all the checks for free!

    public string GetClassName<T> () where T : UpnpObject {
        //do stuff with 'typeof (T)'
    }


    Tada! Using generic type parameters as method parameters is nothing new (Aaron has something like this in the Banshee service stack), but the really neat thing is that you can use the generic constraints as a kind of argument pre-condition. If you have a method which takes a Type, consider using a generic type parameter rather than a method parameter. It guarantees that 'null' cannot be passed and it allows you to specify ancestry, interfaces, ref/value types, and the presence of a default constructor.

    Tuesday, February 3, 2009

    C# 4 is NOW!

    WHAT?
    Generic type variance support just landed in mcs. This is a C# 4 language feature.

    WHERE?
    You can give it a go by checking out SVN trunk and compiling your variant code with gmcs -langversion:future.

    REALLY?
    Well, this adds compiler support for variance but the Mono VM isn't up to speed on its variance handling. This means that you can compile the code but it won't actually run on Mono (until we fix that, which I am also doing). You can run it on the .NET 2.0 VM.

    WHAT THE HELL ARE YOU TALKING ABOUT?
    Generic type variance is like this:

    Let's say I have some IEnumerable<string>, like so:

    IEnumerable<string> myStrings = GetSomeStrings ();


    Now let's say I have some other method which takes an IEnumerable<object>, like so:

    void DoStuff (IEnumerable<object> someObjects)
    {
        foreach (object o in someObjects) {
            // do some stuff with each object
        }
    }


    POP QUIZ: Can I pass myStrings to DoStuff in C# 3? Strings are objects, right? And IEnumerable<T> is just a way of getting Ts. So if strings are objects, and IEnumerable<string> just returns strings, then we can also say that it returns objects. Just like IEnumerable<object>. So it should work, right?

    ANSWER: Negatorz!

    This is a problem of generic type variance. There are two kinds of variance: covariance and contravariance. The above example is covarant, meaning that you want to broaden the type of an output. Contravariance is the opposite: narrowing the type of an input. Let's consider a delegate:

    delegate void Handler<T> (T input);


    And let's say that we have some Handler<object>:

    Handler<object> myHandler = delegate (object o) {
        // do something with the object
    }


    Now let's say that we have a method with takes a Handler<string>

    void HandleStrings (Handler<string> handler, IEnumerable<string> strings)
    {
        foreach (string s in strings) {
            handler (s);
        }
    }


    We want to pass myHandler to HandleStrings. A Handler<object> takes objects, and strings are objects, so anything which is a Handler<object> should also be a legal Handler<string>. This is an example of contravariance.

    It may surprise you to know, but the CLI has supported generic type variance since version 2. The rules are:
    • Variant type parameters are only allowed in interfaces and delegate types.

    • Contravariant type parameters can only be used as by-value method parameter types.

    • Covariant type parameters can only be used as method return types and generic arguments to inherited interfaces.

    • Only reference types are variant (this isn't explicitly stated in the spec, but it is the case).

    • Languages may choose to ignore variance and treat all generic parameters as invariant.


    For whatever reason, the C# language team has so far chosen not to support generic type variance. Well, that will be changing in 2010. The preview given by Anders Hejlsberg at PDC '08 revealed that C# 4 will finally support variance. But who wants to wait? Especially considering that this has been a .NET VM feature since 2006. So you can now use this in gmcs if you pass -langversion:future.

    Covariance (which, as you will remember, can only be used as a method return type or as a generic argument to an inherited interface) is denoted with the "out" keyword before the type parameter identifier:

    interface IFoo<out T> : IBar<T>
    {
        T Bat { get; }
    }


    Contravariance (which is legal only as the type of a by-value method parameter) is denoted with the "in" keyword:

    interface IFoo<in T>
    {
        void Bar (T bat);
    }


    So there you go! Now we just need to get Mono's VM variance support polished off. I'm sure I'll have good news for you about that shortly. Thanks goes to Marek Safar for reviewing patches. If you have questions about how or why variance works (it's kind of tricky to get your head around), leave a comment. I might do a post delving into all of the little rules behind variance.

    Saturday, November 29, 2008

    Equality Now!

    There are three primary ways to handle equality in .NET: overriding Object.Equals, overloading the == and != operators, and implementing IEquatable<T>. Framework Design Guidelines offers pretty good advice on when to use what. A quick summary:
    • If you want custom equality logic, whatever else you might do, override Object.Equals. This method is used by the various data structures in System.Collections (and elsewhere in the BCL) to determine equality. It's the first best way to do equality.
    • IEquatable<T> should be implemented by structs with custom equality. Because calling Object.Equals on a struct involves boxing, and the implementation for value types uses reflection (!!!!!), IEquatable<T> gets around both of those problems. When implementing IEquatable<T>, always override Object.Equals as well.
    • Operator overloading is a little bit tricky because it's really just a compiler feature. The compiler has a lookup rule for the operator implementation which takes the most derived types along the operands' type ancestry. Whereas Object.Equals is a virtual method whose overridden implementation will always be used, overloaded operators will only be used if both operands are of static (compile-time) types that are or derive from the types specified in the overload. Overloading operators is a matter of discretion. It's more commonly done with value than reference types. If you overload the equality operators, also override Equals (an implement IEquatable<T> if the type is a struct).
    When you are just overriding Equals, here is the pattern I find works the best:

    public override bool Equals (object obj)
    {
      MyRefType mine = obj as MyRefType;
      return mine != null && /* custom equality logic here */;
    }

    If you want to overload operators and it's a reference type, here's the thing to do:

    public override bool Equals (object obj)
    {
      MyRefType mine = obj as MyRefType;
      return mine == this;
    }

    public static bool operator == (MyRefType mine1, MyRefType mine2)
    {
      if (Object.ReferenceEquals (mine1, null)) {
        return Object.ReferenceEquals (mine2, null);
      }

      return !Object.ReferenceEquals (mine2, null) &&
      /* custom equality logic here /*;
    }

    public static bool operator != (MyRefType  mine1, MyRefType  mine2)
    {
      return !(mine1 == mine2);
    }

    If you have a value type, here's the scenario without overriding the operators.

    public override bool Equals (object obj)
    {
      return obj is MyValueType && Equals ((MyValueType)obj);
    }

    public bool Equals (MyValueType mine)
    {
      return /* custom equality logic here */
    }

    And here's the value type with operator overloads

    public override bool Equals (object obj)
    {
      return obj is MyValueType && Equals ((MyValueType)obj);
    }

    public bool Equals (MyValueType mine)
    {
      return mine == this;
    }

    public static bool operator == (MyType mine1, MyType mine2)
    {
      return /* custom equality logic here */
    }

    public static bool operator != (MyType  mine1, MyType  mine2)
    {
      return !(mine1 == mine2);
    }

    The purpose of the above patterns is to centralize the equality logic in one place. You'll notice in the example which uses all three approaches, the == operator is the only place with actual equality logic. I find this just makes thing easier. If you want, you can have custom logic in the != overload (the logical inverse of ==), but that means you have to make changes in two places if you alter the equality logic, and it's really easy to make a mistake with logic operators.

    Want to share your tips for equality? Have a better pattern? Leave a comment!

    Wednesday, November 5, 2008

    Advanced Topics in Inefficiency: Anonymous Methods

    This is the first in what may be a series of posts on various theoretical (and not so theoretical) corner cases in common code. Despite being obtuse, these issues are useful to explore both to avoid inefficiencies and to better understand what's happening behind the code. Today's topic: anonymous methods.
    class Foo()
    {
        void Bar()
        {
            var thing1 = new Thing();
            var thing2 = new Thing();

            DoSomeStuff (() => thing1.Shimmy());
            DoOtherStuff(() => thing2.Shake());
        }
    }
    There is a potential memory problem with this method. It's not obvious from looking at the code, but both things must be garbage collected together. As long as there is an active reference to one, the other will live on as well. If 'Thing' is a heavy type, this could keep significant memory from being reclaimed on the heap. To better understand, let us look at how the C# compiler handles anonymous methods.

    The above example demonstrates "local variable capture." This means local variables from the enclosing method body can be used inside closures (such as the two lambdas above). To accomplish this, the C# compiler shunts the values of the local variables to an object. The type of the object is generated by the compiler. In essence, the compiler turns the above code into this:
    class Foo()
    {
        class GeneratedTypeForMethodBar
        {
            public Thing thing1;
            public Thing thing2;

            public void AnonymousMethod1()
            {
                thing1.Shimmy();
            }

            public void AnonymousMethod2()
            {
                thing2.Shake();
            }
        }

        void Bar()
        {
            var closure_object =
                new GeneratedTypeForMethodBar();
            closure_object.thing1 = new Thing();
            closure_object.thing2 = new Thing();

            DoSomeStuff(closure_object.AnonymousMethod1);
            DoOtherStuff(closure_object.AnonymousMethod2);
        }
    }
    This is actually a very clever way of achieving local variable capture since it makes use of the CLI's pre-existing garbage collector to clean up the captured variables. The problem is, the compiler shunts all local variables to a single object. In our above example, the two anonymous methods do not reference any of the same local variables, but both local variables are stored in the same object. This can lead some captured variables to become prisoner variables: they are no longer needed, but they cannot be garbage collected. Suppose that our 'DoSomeStuff' method just invokes the delegate and returns. No problem. But now suppose that our 'DoOtherStuff' method holds on to the delegate, perhaps planing to invoke it later. Or suppose we were to return the second lambda, allowing the caller to hold the delegate as long as they please. That delegate holds a reference to the 'closure_object' which holds a reference to both Things, even though that delegate just needs 'thing2'. There is no way for any code to reach 'thing1' but it won't be garbage collected until we're done with 'thing2'.

    Solution?

    Well, we could modify the compiler to generate a type for each set of local variables that appear in only one anonymous method, like so:
    class Foo()
    {
        class GeneratedTypeForMethodBar1
        {
            public Thing thing1;

            public void AnonymousMethod()
            {
                thing1.Shimmy();
            }
        }

        class GeneratedTypeForMethodBar2
        {
            public Thing thing2;

            public void AnonymousMethod()
            {
                thing2.Shake();
            }
        }

        void Bar()
        {
            var closure_object1 =
                new GeneratedTypeForMethodBar1();
            closure_object1.thing1 = new Thing();

            var closure_object2 =
                new GeneratedTypeForMethodBar2();
            closure_object2.thing2 = new Thing();

            DoSomeStuff(closure_object1.AnonymousMethod);
            DoOtherStuff(closure_object2.AnonymousMethod);
        }
    }
    This poses problems as well. First of all, we are instantiating two (or more) generated-type objects rather than one. Object instantiation is not cheap and that could potentially slow down certain code. Also, this approach cannot be used to optimize more complex scenarios. Suppose we have five anonymous delegates, each referencing some of seven local variables like so: a {1 2} b {2 3} c {3 4 5} d {1 5 6} e {6 7}. In these situations we must default to the one-compiler-generated-type-for-everything approach.

    Ultimately, the lesson here is just to be aware of these potential issues. If you find via profiling that objects are not being garbage collected and you make heavy use of anonymous methods, you might want to examine your closures to make sure this isn't causing the problem.

    And what do people think about modifying the compiler as proposed above? Also, anyone who comes up with a better mechanism for local variable capture gets cool points. Double points if your solution doesn't require VM changes.

    P.S. Thanks to Michael for help with this post.