为什么向下转换取消装箱导致异常?

时间:2010-10-12 02:36:12

标签: c#

我无法弄清楚,为什么以下代码导致异常?

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

编辑:

我认为我的代码可以简化如下:

class Program
{
    static void Main(string[] args)
    { 
        int x = 100;
        object o = x;
        short s = (short)o;
    }
}

5 个答案:

答案 0 :(得分:4)

您正在取消装箱temp,它实际上是int直接插入short,这就是演员失败的原因。相反,您必须首先取消装入正确的类型(int),然后执行整数转换:

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); }
    }
}
其他人建议

编辑,请参阅Eric Lippert的Representation and Identity博客文章,了解详情。

答案 1 :(得分:2)

整数值的直接“强制转换”实际上是转换。当值被加框时,编译器无法发出适当的转换,因此它会尝试转换值。由于类型不相同(Int16和Int32是不同类型),因此拆箱和转换失败。

在旁注中,如果省略强制装箱为对象的临时变量,我猜测代码是否有效。

答案 2 :(得分:2)

Eric Lippert有一篇关于Representation and Identity主题的详细博客文章。这解释了为什么你必须拆箱到原始类型或Nullable&lt;&gt;原始类型。

答案 3 :(得分:2)

正如其他人所说,将值类型拆分为错误类型是违法的。一个快速的解决方案是将参数类型更改为动态或执行此操作:

return (T)(value as dynamic);

您需要支付一些费用,但dlr会将值类型解析为正确类型以进行拆箱。

答案 4 :(得分:-2)

您想将整数(int)强制转换为短整数(short)。由于int支持的位数大于short int,因此原始int的值可能对short int而言过大。为了通知您这个问题,运行时会注意到强制转换 - 与任何强制转换为强制转换的强制转换一样 - 是不允许的。

例如,在32位系统中,int以32位存储值,而短存储值以16位存储。如果一个值为4,000,000的32位int将被转换为16位短路会发生什么? short变量中没有足够的位来存储4,000,000的值。在那种情况下,您期望看到什么?运行时正在提醒您这种溢出情况。