为什么这样做:
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.有时,值将是对象{decimal},T将是double,在这种情况下将抛出InvalidCastException。但原则上这不应该是一个问题,因为值是一个十进制(虽然是一个对象的盒子),可以强制转换为double。
我如何处理这个问题?
答案 0 :(得分:11)
您只能将装箱值类型转换回到装箱的确切类型。如果从装箱类型到您正在投射的类型之间存在隐式或显式转换,则无关紧要to - 你仍然需要转换为盒装类型(为了取消装箱),然后从那里拿走它。
在示例中,这意味着两个连续的演员表:
double dd = (double) (decimal) o;
或者,使用Convert
方法:
double dd = Convert.ToDouble(o);
当然,这不适用于您的实际用例,因为您无法立即从泛型类型参数转到ToDouble
。但只要目标类型为IConvertible
,您就可以执行此操作:
double dd = (double)Convert.ChangeType(o, typeof(double));
其中泛型类型参数T
可以替换double
。
答案 1 :(得分:3)
后者不起作用,因为十进制值被装入一个对象。这意味着要获得价值,您必须先使用投射的相同语法进行拆箱,因此您必须按照以下两个步骤执行此操作:
double dd = (double) (decimal) o;
请注意,第一个(decimal)
是拆箱,(double)
正在投放。
答案 2 :(得分:2)
可以使用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));
}
}
您的代码不起作用的原因已在本文中得到其他人的充分解释。