Free mag vol1 | Page 171

CHAPTER 3  CORE C# PROGRAMMING CONSTRUCTS, PART I As you have just witnessed, an explicit cast allows you to force the compiler to apply a narrowing conversion, even when doing so may result in a loss of data. In the case of the NarrowingAttempt() method, this was not a problem, as the value 200 can fit snuggly within the range of a byte. However, in the case of adding the two shorts within Main(), the end result is completely unacceptable (30,000 + 30,000 = –5536?). If you are building an application where loss of data is always unacceptable, C# provides the checked and unchecked keywords to ensure data loss does not escape undetected. The checked Keyword Let’s begin by learning the role of the checked keyword. Assume you have a new method within Program that attempts to add two bytes, each of which has been assigned a value that is safely below the maximum (255). If you were to add the values of these types (casting the returned int to a byte), you would assume that the result would be the exact sum of each member. static { byte byte byte } void ProcessBytes() b1 = 100; b2 = 250; sum = (byte)Add(b1, b2); // sum should hold the value 350. However, we find the value 94! Console.WriteLine("sum = {0}", sum); If you were to view the output of this application, you might be surprised to find that sum contains the value 94 (rather than the expected 350). The reason is simple. Given that a System.Byte can hold a value only between 0 and 255 (inclusive, for a grand total of 256 slots), sum now contains the overflow value (350 – 256 = 94). By default, if you take no corrective course of action, overflow/underflow conditions occur without error. To handle overflow or underflow conditions in your application, you have two options. Your first choice is to leverage your wits and programming skills to handle all overflow/underflow conditions manually. Of course, the problem with this technique is the simple fact that you are human, and even your best attempts might result in errors that have escaped your eyes. Thankfully, C# provides the checked keyword. When you wrap a statement (or a block of statements) within the scope of the checked keyword, the C# compiler emits additional CIL instructions that test for overflow conditions that may result when adding, multiplying, subtracting, or dividing two numerical data types. If an overflow has occurred, you will receive a runtime exception: System.OverflowException. Chapter 7 will examine all the details of structured exception handling and the use of the try and catch keywords. Without getting too hung up on the specifics at this point, observe the following update: static void ProcessBytes() { byte b1 = 100; byte b2 = 250; // This time, tell the compiler to add CIL code // to throw an exception if overflow/underflow // takes place. try { 105