没有显式转换处理数字的通用方法

时间:2012-04-03 13:03:17

标签: c# generics c#-4.0

我有一个类具有泛型类型的属性,如下所示。类型T可以是任何数字(short,int,float ...)

    public class EqualFilter <T> : Filter {
        private T _value;
        public override T Value {
        get {
            return _value;
        }
        set {
            if (!EqualityComparer<T>.Default.Equals(_value, value)) {
                _value = value;
                RaiseFilteringChanged();
            }
        }
    }
    .....
}

现在我有一个客户端类,其中有一个“String”需要传递给上面的setter。现在在上面的setter中设置值时,类型T已经在运行时确定,我可以在我的客户端中将类型保存为Type T.是否可以在客户端程序中将字符串转换为EqualFilter标识的相应类型?像这样的东西不起作用

Type T = filter.getFilterType();
filter.Value = (T) myTextBox.Text;

以下代码可以使用,但是对于所有可以为数字的类型都会涉及if-else。

Type T = filter.getFilterType();
if (T == typeof(int)) {
    filter.Value = Int32.Parse(myTextBox.Text);
} else if() {
....
}

总之,我不确定如何以更好的方式解决问题。

3 个答案:

答案 0 :(得分:2)

听起来你正在做类似于数据绑定的事情。如果您感兴趣的是使用字符串,您可以考虑将泛型类型约束为IConvertible并从特殊的setter方法调用Convert.ChangeType方法,如下所示:

public class EqualFilter<T> : Filter where T : IConvertible {

    // ... omitted Value property code ...

    public void SetValue(string value)
    {
        Value = (T)Convert.ChangeType(value, typeof(T));
    }

    // ...
}

泛型类型约束仅允许Convert.ChangeType可以操作的那些类型。除了积分和浮点类型之外,还允许使用stringdecimalDateTime类型。请注意,string类型在使用double类型时可能并不总是准确,因为可能存在舍入和浮点表示错误。此外,您可能还需要捕获其他异常,以使其更加健壮(例如FormatExceptionOverflowException)。

void Main()
{
    var a = new EqualFilter<int> { Value = 10 };
    var b = new EqualFilter<double> { Value = 20 };
    b.Value = Math.PI; // RaiseFilteringChanged called - no surprise
    b.SetValue(Math.PI.ToString()); // RaiseFilteringChanged called - surprised?
    Console.WriteLine(b.Value);
    b.SetValue("25");
    Console.WriteLine(b.Value);
    var c = new EqualFilter<DateTime> { Value = DateTime.Today };
    Console.WriteLine(c.Value);
    c.SetValue("12/23/2011");
    Console.WriteLine(c.Value);

    // compiler error object isn't an IConvertible:
    // var illegal = new EqualFilter<object>();
}

在这种情况下,big switch语句由ChangeType方法中的框架处理。

修改 从我上面的代码版本中添加Console.WriteLine输出(具有覆盖和基类使用注释掉):

  

3.14159265358979

     

25

     

4/10/2012 12:00:00 AM

     

12/23/2011 12:00:00 AM

答案 1 :(得分:1)

您可以尝试以下方法:

filter.Value = Convert.ChangeType(myTextBox.Text, filter.getFilterType());

如果未定义转换,则无效。

修改

我没有注意到您的Value属性是通用的。 为了使这项工作,您可以通过以下方式扩展您的过滤器对象:

public object UnsafeValue
{
    set
    {
        Value = (T)value;
    }
}

并将Convert.ChangeType的结果分配给该属性。

每个不修改过滤器类的方法都会涉及调用层次结构中的更多泛型或反射。

答案 2 :(得分:0)

您是否考虑过创建这样的特定setter方法:

public void setValue(object o){
   if (typeof(o) == typeof(Value)) {
       Value = (typeof(Value))o;
   }
}