Narrowing Explicit and Widening Implicit Data Type Conversions

Now that you understand how to interact with intrinsic data types, let's examine the related topic of data type conversion. Assume you have a new Console Application (named TypeConversions) that defines the following module:

Module Program Sub Main()

Console.WriteLine("***** The Amazing Addition Program *****") Dim a As Short = 9 Dim b As Short = 10

Console.WriteLine("a + b = {0}", Add(a, b)) End Sub

Function Add(ByVal x As Integer, ByVal y As Integer) As Integer

Return x + y End Function End Module

Notice that the Add() method expects to be sent two Integer parameters. However, note that the Main() method is in fact sending in two Short variables. While this might seem like a complete and total mismatch of data types, the program compiles and executes without error, returning the expected result of 19.

The reason that the compiler treats this code as syntactically sound is due to the fact that there is no possibility for loss of data. Given that the maximum value of a Short (32,767) is well within the range of an Integer (2,147,483,647), the compiler automatically widens each Short to an Integer by copying the Short into an Integer. Technically speaking, widening is the term used to define a safe

"upward cast" that does not result in a loss of data. Table 3-6 illustrates which data types can be safely widened to specific data types.

Table 3-6. Safe Widening Conversions

VB 2008 Type

Safely Widens to ...

Byte

SByte, UInteger, Integer, ULong, Long, Single, Double, Decimal

SByte

SByte, Integer, Long, Single, Double, Decimal

Short

Integer, Long, Single, Double, Decimal

SByte

UInteger, Integer, ULong, Long, Single, Double, Decimal

Char

SByte, UInteger, Integer, ULong, Long, Single, Double, Decimal

Integer

Long, Double, Decimal

UInteger

Long, Double, Decimal

Long

Decimal

ULong

Decimal

Single

Double

Although this automatic widening worked in our favor for the previous example, other times this "automatic type conversion" can be the source of subtle and difficult-to-debug runtime errors. For example, assume that you have modified the values assigned to the a and b variables within Main() to values that (when added together) overflow the maximum value of a Short. Furthermore, assume you are storing the return value of the Add() method within a new local Short variable, rather than directly printing the result to the console:

Module Program Sub Main()

Console.WriteLine("***** The Amazing Addition Program *****") Dim a As Short = 30000 Dim b As Short = 30000

Console.WriteLine("a + b = {0}", answer) End Sub

Function Add(ByVal x As Integer, ByVal y As Integer) As Integer

Return x + y End Function End Module

In this case, although your application compiles just fine, when you run the application you will find the CLR throws a runtime error, specifically a System.OverflowException, as shown in Figure 3-11.

Figure 3-11. Oops! The value returned from Add() was greater than the maximum value of a Short!

The problem is that although the Add() method can return an Integer with the value 60,000 (as this fits within the range of an Integer), the value cannot be stored in a Short (as it overflows the bounds of this data type). In this case, the CLR attempts to apply a narrowing operation, which results in a runtime error. As you can guess, narrowing is the logical opposite of widening, in that a larger value is stored within a smaller variable. Not all narrowing conversions result in a System. OverflowException, of course. For example, consider the following code:

' This narrowing conversion is a-OK.

Dim myByte As Byte

Dim myInt As Integer = 200

myByte = myInt

Console.WriteLine("Value of myByte: {0}", myByte)

Here, the value contained within the Integer variable myInt is safely within the range of a Byte, therefore the narrowing operation does not result in a runtime error. Although it is true that many narrowing conversions are safe and nondramatic in nature, you may agree that it would be ideal to trap narrowing conversions at compile time rather than runtime. Thankfully, there is such a way, using the VB 2008 Option Strict directive.

Was this article helpful?

0 0

Post a comment