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.