Sep 10

Checked vs unchecked operations

Posted in Basics C#      Comments Off on Checked vs unchecked operations

In the previous post, I’ve introduced the concept of primitive type and we’ve seen how they’re treated in a special way by the compiler. One interesting topic that pops up when we talk about primitive types is operation overload. For instance, what happens when you try to run the following snippet:

var max1 = Int32.MaxValue;
var max2 = Int32.MaxValue;
Int32 max3 = max2 + max1;
.WriteLine(max1 + max2);

MaxValue returns the maximum value that can be stored in an Int32 variable. It’s obvious that trying to save that value into an integer won’t produce the correct result. However, you won’t get an exception if you try to run the previous code. The justification is simple: you see, the CLR offers several IL instructions for doing arithmetic operations. Some, allow overflow to occur silently (ex.: add) because they don’t check for it; others don’t and when that happens, you’ll get an exception (ex.:add.ovf).  As you might expect, the instructions which don’t run an overflow check are faster and those are the ones that are used by default by the C# compiler.

If you want to turn overflow verification for all the code in your assembly, then you can simply use the /checked+ compiler switch. If you’re only interested in checking a specific operator or block of instructions, then you can use the checked operator (there’s also an unchecked operator that does the opposite of that). Here’s a small snippet that shows how you can use these operators:

Int32 max3 = checked( max2 + max1 );

And yes, that should throw an exception at runtime. If you’re interested in running several instructions as checked operations, then the checked statement is for you:

checked {
    var max1 = Int32.MaxValue;
    var max2 = Int32.MaxValue;
    Int32 max3 = max2 + max1;
    Console.WriteLine(max3); Console.WriteLine(max3);

Notice that only the instructions placed directly inside the block will be checked,having no direct impact in method calls.

Many people recommend turning the /checked+ compiler switch on for debug builds for detecting problems associated with code where you’re not using the checked and unchecked blocks/statements. You should probably used the /checked+ option for release builds unless you can’t take the small performance hit associated with the use of the aritmethic checks.

Before ending the post,a small note on the Decimal type. You can’t run checked/unchecked operations against the Decimal type because the CLR doesn’t introduce any instructions for arithmetic operations against it. In practice, that means that the special treatment given to the Decimal type is supported only by the compiler (ie, adding too decimals will always result in invoking the Decimal’s corresponding operation method). So, if you hit an overflow during an arithmetic operation, you’ll end up getting an exception (even when you’re using the unchecked operator or the /checked- compiler switch).

And that’s it. Stay tuned for more.