Why does unboxing lead to an exception when unpacking?

I can’t understand why the following code throws an exception?

static class Utility<T> { public static TReturn Change<TReturn>(T arg) { object temp = arg; return (TReturn)temp; } } class Program { static void Main(string[] args) { int i = 100; try { short s = Utility<int>.Change<short>(i); } catch (Exception ex) { Console.WriteLine(ex); } } } 

Edit:

I think my code can be simplified as follows:

 class Program { static void Main(string[] args) { int x = 100; object o = x; short s = (short)o; } } 
+1
c #
source share
5 answers

You are unpacking temp , which is really int directly in short , so failure will fail. Instead, you need to first remove the desired type ( int ), and then do an integer action:

 using System; class Program { static void Main(string[] args) { int i = 100; object temp = i; try { short s0 = (short)i; short s1 = (short)(int)temp; short s2 = (short)temp; } catch (Exception ex) { Console.WriteLine(ex); } } } 

Edit: as suggested by others, see Eric Lippert Blog Submission and Identification for more details.

+4
source share

Direct "casting" of an integer value is actually a conversion. When a value is inserted into the box, the compiler cannot correct the corresponding conversion, so it tries to use the value instead. Since the types do not match (Int16 and Int32 are different types), unpacking and casting are not performed.

On the side of the note, I assume that the code works if you omit the temporary variable that forces the box for Object.

+2
source share

Eric Lippert has a detailed blog entry on the topic of Presentation and Identification . This explains why you should unpack the source type or Nullable <> of the source type.

+2
source share

According to others, it is illegal to delete a value type with an incorrect type. A quick solution is to change the type of parameters to dynamic or do this:

 return (T)(value as dynamic); 

You pay some costs, but dlr allows value types for the type you want to unpack.

+2
source share

You bind an integer (int) to a short integer (short). Since an int is larger than a short int in terms of the number of bits supported, there is a chance that the original int has a value that is too large for the short int. To notify you of this problem, during the execution of the note that the cast - as with any act when the value is passed to something less - is not allowed.

On a 32-bit system, for example, int stores values ​​in 32 bits and short storage values ​​in 16 bits. What will happen to a 32-bit int with a value of 4,000,000, which will be transferred to a 16-bit short? There is not enough bits in the short variable to hold the value of 4,000,000. What would you expect to see in this case? Runtime alerts you to this overflow condition.

-2
source share

All Articles