13

Is

dataReader[i]

logically equivalent to

dataReader.GetValue(i)

Are they the same? Are they different? Is there a situation where one would be appropriate over the other?

There are documented differently:

  • Gets the column located at the specified index
  • Return the value of the specified field.

But when i use them they both return the value of the field. What does it mean to "get the column"? What does it mean to "return the value of a field"?


Bonus Chatter:

When I call:

reader[i];
reader.GetValue(i);
reader.GetString(i);

i get a String each time

TarasB
  • 2,407
  • 1
  • 24
  • 32
Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219

1 Answers1

18

Ultimately it depends on the particular implementation of System.Data.IDataReader you are referring to, but let's assume you mean System.Data.SqlClient.SqlDataReader.

In this case, reader[i] and reader.GetValue(i) do exactly the same thing. In fact, reader[i] internally calls reader.GetValue(i). (You can see this by disassembling the code using a tool like ILSpy.). Both these members return the value in the i-th column of the current row and will return successfully regardless of the type of the value (the return type is object). The documentation for both of these members is a little misleading and could be worded in a better way. You can use either of these members wherever you like, just pick the one which you feel reads better.

Whereas reader.GetString(i) is specifically designed to return the value contained in the i-th column of the current row as a string. If the value in that column is not a string, an InvalidCastException will be thrown. Use this method when you are sure that the value is a string and string is the type that you want to work with. This will make your code more concise since you won't have to perform a cast.

In your specific case, the value in the i-th column of the current row must be of type string, which is why the return value of all three members is identical.

If written correctly, other implementations of System.Data.IDataReader should behave in the same way.

Adam Ralph
  • 29,453
  • 4
  • 60
  • 67
  • There are horrible edge cases, where `GetValue` returns a `byte`, but `GetInt32` is unable to cast a byte to a Int32 – Ian Boyd Dec 08 '11 at 21:22
  • It's difficult to tell (specially because the disassembled code is hard to follow) but it appears the the value in the column must already be of the desired type otherwise the InvalidCastException (which is itself a little misleading) will be thrown. I'll edit the answer. – Adam Ralph Dec 08 '11 at 21:34
  • Indeed, the documentation for GetInt32 (http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.getint32.aspx) states that "No conversions are performed; therefore, the data retrieved must already be a 32-bit signed integer." The other GetXXX methods are similarly documented. – Adam Ralph Dec 08 '11 at 21:41
  • 3
    @Ian, @Adam: That is simply related to (un)boxing; not directly related to `SqlDataReader`, `IDataReader` etc themselves. Generally, boxed values can only be unboxed to their *exact* type. For example, `object o = (byte)42; int i = (int)o;` will fail with exactly the same error, even though an unboxed `(byte)42` can happily be cast to an `int`. – LukeH Dec 08 '11 at 22:28