Wednesday, 29 October 2008

New Toys! (C# 4.0)

Today I’ve had a chance to play with the VS 2010 CTP VirtualPC image. Specifically, I’ve been playing around with the major new feature for C# 4.0, the DLR integration that allows you to declare an object as dynamic and then perform late bound operations on it. (Please note that it was too much of a pain to get the highlighting working for the dynamic'; just imagine it nice and blue in these code listings.)

I started off very simple :

dynamic hello = "hello world";
Console.WriteLine(hello.ToString());

This worked fine. What happens if I misspell the ToString method?

dynamic hello = "hello world";
Console.WriteLine(hello.ToStrig());

Some sort of runtime error is expected, obviously. Here it is:

 image

Ok, so what is next? Well one thing that occurred to me when I saw the dynamic keyword is that it could be very useful when working with anonymous types. My problem with anonymous types has always been when you go to pass them to another method, you can’t do a whole lot with them when they come out the other side. Lets see if the dynamic keyword can make things nicer:

static void Main(string[] args)
{
    var testObj = new
    {
        Foo = (Action)(() => Console.WriteLine("foo!")),
        Bar = (Action)(() => Console.WriteLine("bar!"))
    };

    DoFooAndBar(testObj);
    Console.ReadLine();
}
static void DoFooAndBar(dynamic foobar)
{
    foobar.Foo();
    foobar.Bar();
}
Output: 
foo!
bar!

Ok well that works. I’m not sure what its good for though. In the past when I’ve wanted to do something like this with anonymous types, it was because I wanted dynamic behaviour. Surely now we have DLR integration, there will be a nicer way to achieve this without having to use anonymous types? I guess I will have to wait and see.

If you would like to read a bit more about dynamic, Chris Burrows has a decent post up. One point I found interesting is that he refers to dynamic as a type. Now the compiler certainly treats it as a type, but the CLR is certainly none the wiser:

static void Main(string[] args)
{
    List<dynamic> list = new List<dynamic>();
    Console.WriteLine(list.GetType());
    Console.ReadLine();
}
Output: 
System.Collections.Generic.List`1[System.Object]

Also, calling typeof(dynamic) won’t even compile:

image

So its a type, but not really. If you take a look at Chris’s post, he shows what the c# compiler generates when the dynamic type is used, and its quite clear that the resulting IL does not involve any “dynamic” type.

Another thing I tried was dynamic invocation of explicit interface implementation:

interface IFoo { void Foo(); }
class Foo : IFoo
{
    void IFoo.Foo() { Console.WriteLine("foo!"); }
}
static void Main(string[] args)
{
    dynamic foo = new Foo();
    foo.Foo();
    Console.ReadLine();
}

It doesn’t work. You get the same error as when I tried calling ToStrig() above. Static methods won’t work either:

class Foo
{
    static void DoFoo() { Console.WriteLine("foo!"); }
}
static void Main(string[] args)
{
    dynamic foo = new Foo();
    foo.DoFoo();
    Console.ReadLine();
}

Again, a RuntimeBinderException occurs. This behaviour is interesting. Here is an excerpt of the new features document (avaliable from the csharp futures site) discussing the C# runtime binder:

This is essentially a part of the C# compiler running as a runtime component to “finish the work” on dynamic operations that was deferred by the static compiler.

Its not JUST deferred. The binder is obviously not behaving precisely the same as the C# compiler. It doesn’t really surprise me that its not exactly the same. I’m sure someone will be able to give me a reasonable explanation.

The last thing I tried today was making a dynamic call within an expression tree:

static void Main(string[] args)
{
    dynamic hello = "hello world";
    Expression<Action> expTree = () => hello.ToString();
}

This fails to compile, while this is fine:

static void Main(string[] args)
{
    dynamic hello = "hello world";
    Action action = () => hello.ToString();
}

The new features document does not list this as one of the known limitations, so perhaps support for dynamic calls within expression trees is coming and just not yet implemented?

Saturday, 11 October 2008

C# in Depth

This is a book review for C# in Depth, by Jon Skeet. I started reading Jon's blog sometime around February this year, and found it to be quite great. I really enjoyed his attention to detail and curiosity about how things work. Jon struck me as someone that likes to teach, but takes great care when doing so to avoid myths, over generalizations or terminology misuse; he cares just as much about buggy communication as he does about buggy programs. Wanting to read more of his writing, I picked up C# in Depth and was very happy to discover a book crafted with the same dedication to detail and thoroughness that first attracted me to his blog.

C# in Depth has a very specific focus. It is aimed at developers that know C# 1, and want to learn the ins and outs of C# 2 and 3. When I say C#, I really mean just the language - the book does not cover the CLR or the class libraries. I expected some of the book to be familiar territory for me as I was already quite familiar with C# 2 and this was indeed the case. But it turns out there were still quite a few gaps in my C# 2 knowledge that the book helped fill in (for example, the distinction between unbound, open and closed generic types).

I particularly enjoyed the section on covariance and contravariance for generics. Specifically, Jon provided examples of particular covariant and contravariant operations that would be useful but are not currently supported. These examples were excellent. I have ran into similar sorts of situations in the past but never really understood how they could be potentially fixed. I have long struggled with the concepts of covariance and contravariance, mostly because I read the definition once every year and it never sticks, I have a glimmer of hope that this time it will.

The C# 3 content is great. I had a basic understanding of how each of the new features contribute to LINQ as a whole, but again there were plenty of gaps in my knowledge that the book helped with. I learned a great deal, in particular, from the section on LINQ query expressions and how they are converted to the underlying code.

In my opinion, C# in Depth is more of a teaching book than a reference book. I can still imagine myself referring back to particular parts that did not quite manage to stick, but really it is designed primarily to deliver an instructive lesson. This, however, should by no means be taken as a criticism. I found the teaching style made the book quite easy to read. Jon’s style is precise, and yet never stale. If only more books with such technical content were so pleasant and carefully edited (I do not recall noticing any technical errors).

C# in Depth rocks. Many times during my journey through the book I found myself breaking out for some special time with the C# compiler, just to see what sort of clever tricks we could get up to. The book has brought me closer to mastery of my current tool of choice. If you are a C# programmer and have a natural curiosity about its capabilities, details, and limitations then I am sure you will find this book rewarding.