C#泛型类型转换Decimal转换为Float - “不能转换类型'T1'? 'T2'“
问题描述:
我想实现一个类,在IntegerUpDown和DecimalUpDown WPF控件上执行泛型功能。使用下面定义的类(简化说明)。 TDataType将为int或float。 TUpDownControl将是要么IntegerUpDown或DecimalUpDown WPF控件 TControlDataType将是整数或小数点C#泛型类型转换Decimal转换为Float - “不能转换类型'T1'? 'T2'“
class MyGenericClass<TDataType, TUpDownControl, TControlDataType>
where TControlDataType : struct, IComparable<TControlDataType>, IFormattable
where TDataType : struct, IComparable, IComparable<TDataType>
where TUpDownControl : CommonNumericUpDown<TControlDataType>
{
private TUpDownControl m_control;
public MyGenericClass(TUpDownControl ctrl)
{
m_control = ctrl;
}
public TDataType getVal()
{
TDataType val = (TDataType)m_control.Value;
return val;
}
}
我遇到的问题是,当我尝试获取价值和小数/整数转换为浮动/诠释我得到错误 “无法转换类型'TControlDataType?' 'TDataType'“ 有没有人有一个想法如何绕过这个?
谢谢
答
该转换不能实际工作;您不能在运行时从一种值类型转换为另一种值类型。
(如(float)myDecimal
代码只能是因为编译器生成IL实际转换值,也不会发生仿制药)
相反,你可以使用Convert.ChangeType()
到装箱值显式地转换为任何其他数值类型。
但是,这是比较慢;它涉及两个box/unbox对和一个虚拟接口调用。
要快,您可以使用表达式树编译自己的转换器:
static class ConverterHolder<TIn, TOut> {
public static Func<TIn, TOut> Converter;
static ConverterHolder() {
var parameter = Expression.Parameter(typeof(TIn));
Converter = Expression.Lambda<Func<TIn, TOut>>(
Expression.Convert(parameter, typeof(TOut)),
parameter
);
}
}
答
你限制不定义TDataType
和TControlDataType
之间的关系,所以编译器无法验证,转换会成功。不幸的是,float
和decimal
之间没有关系,您可以使用它来定义约束条件。但是,您应该可以使用TypeConverter
或来提供转换。
感谢您的回复。我对c#比较陌生,并且不熟悉表达式树。你能再解释一下吗?例如我会有一个像ConverterHolder = Expression ....的行。表达是什么将执行转换? –
user1400716
2014-09-04 22:24:10
@ user1400716:如果您是C#的新手,表达式树会变得复杂(这是您在运行时编译代码的方式)。只需要使用Convert.ChangeType。 – SLaks 2014-09-05 00:15:35
非常感谢您的详细解释和解决方案。 – user1400716 2014-09-05 09:31:31