views:

542

answers:

3

What are the advantages of replacing (int)reader[0] with reader.GetInt32(0)? I'm sure such casting functions are there for a reason, but other than it feeling more aesthetically pleasing to avoid the cast myself, I'm not sure what those reasons are.

A: 

The former can also accept the column name as a string rather than an index, and will attempt to cast the column value to an int. The latter only accepts the index and no casting will be performed.

Joel Coehoorn
+4  A: 

In code....

        void OneWay()
        {
            System.Data.SqlClient.SqlDataReader reader = null;
            int i = reader.GetInt32(0);
        }

        void OtherWay()
        {
            System.Data.SqlClient.SqlDataReader reader = null;
            int i = (int)reader[0];
        }

In IL

.method private hidebysig instance void OneWay() cil managed
{
    .maxstack 2
    .locals init (
        [0] class [System.Data]System.Data.SqlClient.SqlDataReader reader,
        [1] int32 i)
    L_0000: nop 
    L_0001: ldnull 
    L_0002: stloc.0 
    L_0003: ldloc.0 
    L_0004: ldc.i4.0 
    L_0005: callvirt instance int32 [System.Data]System.Data.Common.DbDataReader::GetInt32(int32)
    L_000a: stloc.1 
    L_000b: ret 
}


.method private hidebysig instance void OtherWay() cil managed
{
    .maxstack 2
    .locals init (
        [0] class [System.Data]System.Data.SqlClient.SqlDataReader reader,
        [1] int32 i)
    L_0000: nop 
    L_0001: ldnull 
    L_0002: stloc.0 
    L_0003: ldloc.0 
    L_0004: ldc.i4.0 
    L_0005: callvirt instance object [System.Data]System.Data.Common.DbDataReader::get_Item(int32)
    L_000a: unbox.any int32
    L_000f: stloc.1 
    L_0010: ret 
}

So, the IL is different, but I doubt that there is any noticeable difference between them. Maybe after a million iterations you will see the difference, but not likely.

StingyJack
That unbox.any stands out to me, but you're probably right: upvote.
Joel Coehoorn
Oh: I'm also curious about the _result_ of the code if the the query had, say, a double in that column rather than an int.
Joel Coehoorn
unbox is probably cause the reader[0] syntax returns a boxed integer (as object), and that is the crux of it I guess... in the "one way" the call to DbDataReader::GetInt32() returns an Int32, and so there is no boxing/unboxing happening... Thx!
Charles Bretana
It would probably be worth doing to get the IL of the SqlDataReader.GetInt32 and get_Item(int32) methods to see what the diff is. I imagine that there has to be casting going on in one spot or another.
StingyJack
+1  A: 

reader[0] returns an System.Object, (int)reader[0] is actually doing a cast from Object to Int32.

If you call GetXXX(0) methods, no conversions are performed. Therefore, the data retrieved from the stream must already be the type the method specified.

If the type of data retrieved doesn't match or the column has DBNull, it throws an InvalidCastException.

Liwen