开发者

Why does downcast unboxing result in exception?

I cannot figure out, why the follo开发者_如何学Gowing code results in 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;
    }
}


You're unboxing temp which is really an int directly into a short, that's why the cast fails. Instead, you have to unbox to the right type (int) first, and then do the integer cast:

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); }
    }
}

See Eric Lippert's Representation and Identity Representation and Identity blog entry for lots of details.


As others have said it is illegal to unbox a value type to the wrong type. A quick solution is to change the parameters type to dynamic or to do this:

return (T)(value as dynamic);

You'll pay some costs but the dlr does resolve value types to the right type for unboxing.


A direct 'cast' of an integer value is actually a conversion. When the value is boxed, the compiler cannot emit an appropriate conversion, so it attempts to cast the value instead. Since the types are not the same (Int16 and Int32 are different types), the unboxing and cast fails.

On a side note, I'm guessing the code works if you omit the temporary variable that forces the boxing to Object.


Eric Lippert has a detailed blog entry on the topic of Representation and Identity. Which explains why you must unbox to either the original type or a Nullable<> of the original type.


You are tying to cast an integer (int) to a short integer (short). Since an int is larger than a short int with regards to the number of bits it supports, there is a possibility that the original int has a value that is too large for the short int. To notify you of this issue, the runtime notes that the cast -- as with any cast where a value is cast to something smaller -- is not allowed.

In a 32-bit system, for example, an int stores values in 32 bits and a short stores values in 16 bits. What would happen with a 32-bit int with a value of 4,000,000 that would be cast to a 16-bit short? There are not enough bits in the short variable to store a value of 4,000,000. What would you expect to see in that case? The runtime is alerting you to this overflow condition.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜