To “as” or not to “as”
Iris Classon is asking and finding answers for “stupid” questions on her blog. First of all, they are definitely not stupid questions. There are a lot of nuances of .NET that slip out of our daily thinking. When I first started my Getting Geeky with the .NET Framework series I’d ask really hot coders basic questions – things that affect how code runs – and the results were not stellar. So, first, three cheers for Iris’s project.
Today’s question was “How should I do casting in C#? Should I use the prefix cast or the as-cast?” She’s got some good input that I suggest you read first. I also felt that the discussion left out a significant factor - debugging.
If the value resulting from the cast really should not be null, the code becomes unstable or incorrect at the point of the cast. Period. With the prefix cast, application state clearly becomes incorrect at that point because an exception occurs. With the “as” cast, the application state still becomes incorrect at that point, you just don’t know it. If the value should not be null, you’ll get a null exception, or possibly failure of a Requires clause if you’re using code contracts somewhere, sometime later in application execution.
One of the things that makes hard bugs hard is when there is a disconnect in time or space between the cause and the symptom. Time is time, space is lines of code, assembly placement, etc. Code can be written to minimize these disconnects. One of the ways to do that is to fail quickly. When application state becomes incorrect, yell about it immediately and rarely continue with the application in an invalid state. A null-reference exception at an unexpected time just makes code more difficult to debug.
Eric Lippert’s quote short-cutted the idea of what happens next. He’s quoted as saying that a prefixing cast failure requests, “then please crash the program.” That would be much better put as “then please do not continue the current operation.” Our programs need never crash in the sense of blue screen ugly death. Exception handling is a mechanism for recovering to a valid state, with the capacity to communicate failure to interested parties like the user and system logs.
So, use the “as” cast only when the resulting null does not make the application state incorrect, or you have an immediate and adjacent test that you prefer to make the application state correct or perform different exception management. For example, you might want to add a specific error message if the invalid cast indicates a particular type of problem.
I think the prefixing cast should be the “go to” cast for .NET – the one you use when you haven’t thought through the implications of the null value to the remainder of your program.