从对象框类型的通用铸造

tyr*_*pex 4 c# generics boxing unboxing casting

为什么这样做:

decimal dec = new Decimal(33);
double dd = (double) dec;
Console.WriteLine(dd);
Run Code Online (Sandbox Code Playgroud)

但不是这个:

decimal dec = new Decimal(33);
object o = (object)dec;
double dd = (double) o;
Console.WriteLine(dd);
Run Code Online (Sandbox Code Playgroud)

第二个例子抛出:

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

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

public T GetValue(string q)
Run Code Online (Sandbox Code Playgroud)

从数据源获取值.这些值的类型是未知的,但该方法假定它可以将值转换为T.有时,值将是对象{decimal},T将是double,在这种情况下将抛出InvalidCastException.但原则上这不应该是一个问题,因为值是一个小数(虽然是一个对象的盒子),可以强制转换为double.

我该如何处理这个问题呢?

Jon*_*Jon 12

您只能将盒装值类型转换回装入的确切类型.如果从盒装类型到您要投射的类型的隐式或显式转换无关紧要 - 您仍然必须转换为盒装类型(为了取消装箱),然后从那里拿走它.

在示例中,这意味着两个连续的强制转换:

double dd = (double) (decimal) o;
Run Code Online (Sandbox Code Playgroud)

或者,使用Convert方法:

double dd = Convert.ToDouble(o);
Run Code Online (Sandbox Code Playgroud)

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

double dd = (double)Convert.ChangeType(o, typeof(double));
Run Code Online (Sandbox Code Playgroud)

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