C# C“泛型类型将十进制转换为浮点-”;无法转换类型';T1?&x27;至';T2和x27&引用;

C# C“泛型类型将十进制转换为浮点-”;无法转换类型';T1?&x27;至';T2和x27&引用;,c#,generics,decimal,C#,Generics,Decimal,我试图实现一个类,该类在IntegerUpDown和DecimalUpDown WPF控件上执行通用功能。使用下面定义的类(为便于说明而简化)。 TDataType将为int或float。 TUpDownControl将是IntegerUpDown或DecimalUpDown WPF控件 TControlDataType将为整数或十进制 class MyGenericClass<TDataType, TUpDownControl, TControlDataType> wher

我试图实现一个类,该类在IntegerUpDown和DecimalUpDown WPF控件上执行通用功能。使用下面定义的类(为便于说明而简化)。 TDataType将为int或float。 TUpDownControl将是IntegerUpDown或DecimalUpDown WPF控件 TControlDataType将为整数或十进制

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;
    }
}
class MyGenericClass
其中TControlDataType:struct、IComparable、IFormattable
其中TDataType:struct,IComparable,IComparable
其中TUpDownControl:CommonNumericUpDown
{
私有控制m_控制;
公共MyGenericClass(TUpDownControl ctrl)
{
m_control=ctrl;
}
公共TDataType getVal()
{
TDataType val=(TDataType)m_control.Value;
返回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
        );
    }
}
静态类转换器{
公共静态Func转换器;
静态转换器文件夹(){
var参数=表达式参数(typeof(TIn));
Converter=Expression.Lambda(
Expression.Convert(参数,typeof(TOut)),
参数
);
}
}

您的约束没有定义
TDataType
TControlDataType
之间的关系,因此编译器无法验证转换是否成功。不幸的是,
float
decimal
之间没有可以用来定义约束的关系。但是,您应该能够使用
TypeConverter
Convert.X
来提供转换。

感谢您的回复。我对c#比较陌生,对表达式树也不熟悉。你能再解释一下吗。e、 g.我会有一行像ConverterHolder=Expression。。。。;。要执行转换,表达式将是什么?@user1400716:如果您是C#新手,那么表达式树太复杂了(这是您在运行时编译代码的方式)。只需使用
Convert.ChangeType
。非常感谢您的详细解释和解决方案。我一直在阅读表达式树,但给出的示例与类型转换无关,也不涉及holder类。我很想了解你的建议。你能详细介绍一下吗?如果需要,我可以创建另一个问题。@user1400716:holder类的目的只是为每对类型保存一个不同的编译表达式树。您需要类似于
Expression.Lambda(Expression.Convert(parameter,typeof(TOut)),parameter)
的内容,其中
parameter
Expression.parameter(typeof(TIn))
。确切的语法可能略有不同。