【问题标题】:generic casting from object-boxed type对象装箱类型的泛型转换
【发布时间】:2013-11-22 13:36:23
【问题描述】:

为什么会这样:

decimal dec = new Decimal(33);
double dd = (double) dec;
Console.WriteLine(dd);

但不是这个:

decimal dec = new Decimal(33);
object o = (object)dec;
double dd = (double) o;
Console.WriteLine(dd);

第二个例子抛出:

System.InvalidCastException:指定的强制转换无效。

这个问题来自我有一个通用方法的情况

public T GetValue(string q)

从数据源获取值。这些值的类型是未知的,但该方法假定它可以将值强制转换为 T。有时值将是 object{decimal} 并且 T 将是 double,在这种情况下将抛出 InvalidCastException。但原则上这不应该是一个问题,因为该值是一个可以转换为双精度的小数(尽管被一个对象装箱)。

我该如何处理?

【问题讨论】:

    标签: c# generics casting boxing unboxing


    【解决方案1】:

    您只能将装箱的值类型转换回到被装箱的确切类型。从装箱类型到您要转换的类型是否存在隐式或显式转换都没有关系to -- 你仍然必须强制转换为装箱类型(以便取消装箱),然后从那里取出。

    在示例中,这意味着两个连续的演员表:

    double dd = (double) (decimal) o;
    

    或者,使用Convert 方法:

    double dd = Convert.ToDouble(o);
    

    当然,这不适用于您的实际用例,因为您不能立即从泛型类型参数转到ToDouble。但是只要目标类型是IConvertible,就可以这样做:

    double dd = (double)Convert.ChangeType(o, typeof(double));
    

    其中泛型类型参数T 可以替换double

    【讨论】:

      【解决方案2】:

      后者不起作用,因为十进制值被装箱到对象中。这意味着要取回值,您必须首先使用 casting 的相同语法拆箱,因此您必须分两步完成,如下所示:

      double dd = (double) (decimal) o;
      

      注意第一个(decimal)是拆箱,(double)是铸造。

      【讨论】:

        【解决方案3】:

        这可以通过Convert.ChangeType来完成:

        class Program
        {
            static void Main(string[] args)
            {
                decimal dec = new Decimal(33);
                object o = (object)dec;
                double dd = GetValue<double>(o);
                Console.WriteLine(dd);
            }
        
            static T GetValue<T>(object val)
            {
                return (T)Convert.ChangeType(val, typeof(T));
            }
        }
        

        其他人在这篇文章中已经很好地解释了您的代码不起作用的原因。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-05-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-01-08
          相关资源
          最近更新 更多