Returning Strongly Typed Column Values
Up to this point, you've retrieved column values from a DataReader only as generic
objects of the System.Object class (such objects are often referred to as being of the C#
Note All classes in C# are derived from the System.Object class.
I'll rewrite the while loop shown in the example in the previous section to show how you
store column values as objects of the System.Object class:
object productID =
object productName =
object unitPrice =
object unitsInStock =
object discontinued =
Console.WriteLine("productID = " + productID);
Console.WriteLine("productName = " + productName);
Console.WriteLine("unitPrice = " + unitPrice);
Console.WriteLine("unitsInStock = " + unitsInStock);
Console.WriteLine("discontinued = " + discontinued);
This code results in the same output as Listing 9.1. All I did in Listing 9.1 is to explicitly
show that a DataReader returns a column value as an object of the System.Object class by
default. When an object of the System.Object class is displayed by the
Console.WriteLine() method, the object is first implicitly converted to a string and then
That's fine for just displaying the column values, but what if you want to perform some
kind of calculation with a value? To do that, you must first cast the value to a specific
type. The following example casts the unitPrice object to a decimal and then multiplies it
decimal newUnitPrice = (decimal) unitPrice * 1.2m;
Note You add an m to the end of a literal number to indicate it is of the decimal type.
Casting an object to a specific type works, but it's not very elegant. It also goes against
the one of the main benefits of a modern programming language: use of strong typing.
Strongly typing means that you pick the type of a variable or object when declaring it.
The main benefit of strong typing is that you're less likely to have runtime errors in your
programs that are caused by using the wrong type. This is because the compiler checks
your code to make sure the context of the type is correct.
The bottom line is that you should endeavor to make all your variables and objects of the
appropriate type to begin with, and use casting only when you have no other choice. In
this case, you have a choice: instead of casting, you can use one of the DataReader
object's Get* methods to return a column value in an appropriate type.
Note I use the asterisk in Get* to indicate there are many methods that start with Get.
You can see all the Get* methods in Table 9.2, shown earlier.
For example, one of the Get* methods is GetInt32(), which returns a column value as an
int value. The following code shows the use of the GetInt32() method to obtain the
column value for the ProductID column as an int:
int productID =
As you can see, you pass the ordinal of the column that has the value you want to obtain
to the Get* method. You saw how to get a column's ordinal value in the previous section.