特定数据类型的重载通用方法

时间:2009-08-03 12:24:30

标签: c#

我有一个方法,通过用户传递一些输入值,传递一个Func委托,返回新值(非常简化为我想要实现的目标)

    public L Coerce<L>(string value, Func<string, L> coercer)
    {
        return coercer(value);
    }

    Coerce<int>("123", v => int.Parse(v));

这很好但是我也希望能够编写覆盖特定类型行为的方法,例如......

    public int Coerce<int>(string value)
    {
        return Coerce<int>(value, v => int.Parse(v));
    }

所以基本上叫

    Coerce<int>("123"); // equivalent Coerce<int>("123", v => int.Parse(v));

将节省我不得不为每个Coerce重写int.Parse。当然,这应该扩展到句柄

    public decimal Coerce<decimal>(string value)
    {
        return Coerce<decimal>(value, v => int.Parse(v));
    }

Etc等。

这可以整齐地完成吗?

詹姆斯

4 个答案:

答案 0 :(得分:6)

好吧,如果你真的不想做

Convert.ToInt32(value)

然后这将按照你的要求行事:

public T Coerce<T>(string value) where T : IConvertible
{
    return (T)(((IConvertible)value).ToType(typeof(T),
       CultureInfo.InvariantCulture));
}

因此:

int x = Coerce<int>("123");

byte b = Coerce<byte>("123");

如果您尝试强制转换为不可转换类型,则会出现编译时错误,例如:

var x = Coerce<MyClass>("123"); //compile-time error

在这种情况下,您强制调用者使用Coerce(string value, Func<string,T> coercer)重载。

答案 1 :(得分:1)

您可以使用非通用版本:

public int CoerceInt32(string value)
{
    return Coerce(value, int.Parse);
}

答案 2 :(得分:0)

这种方法的目的是什么?

你为什么要写这个:

int x = Coerce<int>("123", v => int.Parse(v));

而不仅仅是这个:

int x = int.Parse("123");

然而,要回答你的问题,不,不要“整齐地”。 .Parse是int和decimal类型的静态方法,因此无法通过泛型类型使用。

您可以期望的最好的方法是为每个要处理的类型编写一个重载,或者在方法中编写反射代码以确定要调用的静态方法。

因此,当你写这篇文章时会遇到问题:

MyMagicType x = Coerce<MyMagicType>("123");
那么呢?你会假设MyMagicType有一个.Parse方法吗?

答案 3 :(得分:0)

我担心C#不像C ++那样有模板覆盖。我遇到了类似的情况,我必须解决的方法是在运行时检查类型:

public void DoStuff<T>(Dictionary<object, T> arg) {
    // ....
    if (typeof(T) == typeof(ClassA)) {
        DoStuff((Dictionary<object, ClassA>)arg);
    }
    else (typeof(T) == typeof(ClassB)) {
        DoStuff((Dictionary<object, ClassB>)arg);
    }
    else {
        throw new ArgumentException("T must be ClassA or ClassB");
    }
}