Monday, 7 December 2009

is, then as (C#)


The C# language has a pair of related operators, is and as. Say you have an object, x, and you want to know if its really type Form underneath.

(x is Form) will be true if it is, or false if it isn't. The as operator will actually perform the conversion, returning null if it can't be converted to that type.

One common piece of advice to C# programmers is to avoid using the is operator. Here's how both of these operators are typically used together.
    if (x is Form)
    {
        Form frm = x as Form;
        /* Use frm. */
    }

While the code works, all the is operator is doing is performing an as operation, and checking if the result is null or not. In other words, (x is Form) is equivalent to (x as Form != null). This means the code above is really saying...
    if (x as Form != null)
    {
        Form frm = x as Form;
        /* Use frm. */
    }

See that. The same as operation was done twice. What a waste! So, the standard advice is to re-write the code to use just one as operation.
    Form frm = x as Form;
    if (frm != null)
    {     
        /* Use frm. */
    }

Simple. So what's the point of this article? Why use is at all?

The problem for me is that is just looks so darn nice. Beginners very quickly understand what's going on when they see it. The re-written code that checks for null just doesn't look as pretty and isn't as obvious what's going on.

You may be wondering what the cost of this additional operation is. I knocked together a quick test which looped is-then-as and then looped the optimized version the same number of times and reported the difference in time. When I increased the count to 100,000,000, I saw approx one second difference build up. That's a lot of looping.

But hey, that cost is non-zero, and I'm wondering why. Compilers are pretty good these days. I recall advice from long ago that its better to use an XOR operation to check if two values are equal, or to use shift operations instead of multiplying. These days, best practice to write what you mean and leave micro-optimizations to the compiler. So why doesn't Microsoft's C# compiler optimize is-then-as into a single operation?

I don't know. It could be that its not worth the development team's time, or maybe there's a subtle reason that escapes me right now. I wish I knew. But if we could eliminate the repeated operation and use is freely, code would be lot nicer to look at.

Picture credit: Fruit balance by Pickersgill Reef.
Many thanks to Eric Lippert and the commentators to his article that inspired this piece.
Update 18/Jan/2010: Introduction modified to be better understood by non C# programmers. (Thanks Andrew.)

No comments:

Post a Comment