Why does this cast from short to int fail?

12,970

Solution 1

What you have in your hands is an instance of unboxing. Specifically when unboxing, you can only unbox to the type of the value that was originally boxed; if that type is A and you are unboxing to B, it does not matter if an implicit conversion from A to B exists (the unboxing will still fail).

See Eric Lippert's classic blog post on the subject for an involved explanation.

Solution 2

You have to cast to the very specific type since you are unboxing - the problem is that oReader["Duration"] returns an object instance:

short myShort = 42;
object o = myShort;
int myInt = (int)o; //fails

It will succeed if you cast back to short first, then to int:

(int) (short) oReader["Duration"]
Share:
12,970
A. Wilson
Author by

A. Wilson

Application security professional (since 2015) with a background in software development (since 2007) Deeply familiar with SAST tools Checkmarx and Fortify, including workflows to scale these at enterprise level. Working knowledge of Burp Suite and OWASP Zap Familiarity with web pen testing methods and tools Experience as full time C#/.NET developer (2007-2015) Working knowledge of Python and Java Excel at delivering solutions in a tech leadership role

Updated on June 07, 2022

Comments

  • A. Wilson
    A. Wilson almost 2 years

    We have some code that archives data from a Microsoft Access database into a MS SQL Server database. Assuming we have a data reader already populated from the Access table and we are adding a parameter to a SqlCommand in preparation for the insert, we have a typecast that is failing. Here is the code:

    oSqlServerDbCmd_ForInsert.Parameters.AddWithValue("@Duration",
         (int) oReader["Duration"]);
    

    The field from the oReader is actually an Access Integer, which is a short in C#. If we cast to a short here there is no problem. However, if we cast to an int the code throws an InvalidCastException. I may be misreading this from the MSDN documentation:

    "There is a predefined implicit conversion from short to int, long, float, double, or decimal."

    ...but it sounds like this should work (my reasoning being, if an implicit conversion is defined why would an explicit typecast not work?). I realize the cast is not even necessary because AddWithValue accepts an object, so we have actually removed the cast from our code, but I would love to see an explanation as to why this cast was failing just in case we run into something like this in the future.

    • Bryan Crosby
      Bryan Crosby about 12 years
      Good article from Eric Lippert on this blogs.msdn.com/b/ericlippert/archive/2009/03/19/…
    • phoog
      phoog about 12 years
      This is not an answer to your question, but it seems like your @Duration parameter should have a numeric data type, in which case you would not want to use a string value in the AddWithValue call.
    • A. Wilson
      A. Wilson about 12 years
      @phoog I edited the code to remove that conversion as it is a distraction from what this question really ended up being about. The short answer is that the string conversion was in the code when we inherited it. Since it was working until we changed the data type in the source DB we'd had no cause to investigate the code. Once it was broken and we dug in we saw that the string conversion was unnecessary (although not problematic, believe it or not).
  • Ed S.
    Ed S. about 12 years
    +1 I always forget about that. object o = (short)10; int i = (int)o; fails.
  • A. Wilson
    A. Wilson about 12 years
    Ah that makes sense. So, were I to first cast it as a short I could then cast it as an int with no issue?
  • A. Wilson
    A. Wilson about 12 years
    Thanks for the feedback, +1...you both answered my question so I'm going to have to go with first mover.