2012-07-21 55 views
4

值类型,我有以下代码:如何使用泛型

public class Class1 
{ 
    void ValueSpecific(string arg) 
    { 
     // do string stuff 
    } 
    void ValueSpecific(int arg) 
    { 
     // do int stuff 
    } 
    void ValueSpecific(float arg) 
    { 
     // do float stuff 
    } 
    void ValueGeneric(string arg) 
    { 
     // do stuff 
     ValueSpecific(arg); 
     // do more stuff 
    } 
    void ValueGeneric(int arg) 
    { 
     // do stuff 
     ValueSpecific(arg); 
     // do more stuff 
    } 
    void ValueGeneric(float arg) 
    { 
     // do stuff 
     ValueSpecific(arg); 
     // do more stuff 
    } 
    void Main(string s, int i, float f) 
    { 
     ValueGeneric(s); 
     ValueGeneric(i); 
     ValueGeneric(f); 
    } 
} 

这工作,但ValueGeneric的全部三个重载的机体的是相同的。我想将它们合并成一个方法,它看起来是这样的:

void ValueGeneric<T>(T arg) where T: string, float, int 
{ 
    // do stuff 
    ValueSpecific(arg); 
    // do more stuff 
} 

但是这当然是无效的C#。 我能想出的最好的是:

void ValueGeneric(object arg) 
{ 
    // Do stuff 
    if (arg is int) 
    { 
     ValueSpecific((int)arg); 
    } 
    else if (arg is string) 
    { 
     ValueSpecific((string)arg); 
    } 
    else if (arg is float) 
    { 
     ValueSpecific((float)arg); 
    } 
    else 
    { 
     Debug.Assert(false, "Invalid type) 
    } 
    // Do more stuff 
} 

但这似乎非常不雅。我会很感激任何建议。 (虽然我会感兴趣的任何解决方案,一个.NET3.5的支持是最好的,因为这是我在用的。)

+0

当你确实想做到这一点,你必须诉诸使用反射。 – 2012-07-21 08:58:46

+0

扩展方法怎么样? – 2012-07-21 09:02:06

+0

@JeffMercado是对的。如果你想要它的优雅,你必须使用反射。 – pikzen 2012-07-21 09:04:42

回答

2

假设你在做之前和之后一样的东西,在你所有的重载,您可以应用通常的方法来分解代码中的不同内容并对它们进行参数化。唯一改变的是传入的参数以及您对该参数执行的操作。通过他们无论在。

static void ValueGeneric<T>(T arg, Action<T> action) 
{ 
    // do stuff 
    action(arg); 
    // do more stuff 
} 

然后调用使用适当的行动泛型方法(您ValueSpecific重载将很好地解决自身)。

ValueGeneric(s, ValueSpecific); 
ValueGeneric(i, ValueSpecific); 
ValueGeneric(f, ValueSpecific); 
+0

我喜欢那个。谢谢。 BTW有一大堆其他的答案在这里一分钟前,其中一名来自HatSoft所用“动态”(这onoy .NET 4的作品),但他们已经全部消失了。幸运的是我抓住了HatSoft的解决方案。 HatSoft,你是否删除它,或者是有人在主持页面? – Dave 2012-07-21 09:37:22

+0

@Dave。我删除了我的,因为它不会是我会承诺的解决方案。其他人也可能效仿。 “动态”解决方案可以工作,但您最好有具体的方法来确保您在编译时发现问题,而不是冒着运行时错误的风险。 – 2012-07-21 20:35:31

0

从我看到的其他大型.NET项目中,您可以包括特定的和通用的重载。如果一个特定的过载不存在,他们就会使用,而不是通用的版本:

void ValueGeneric(int i); 
void ValueGeneric(string s); 
void ValueGeneric(float f); 
void ValueGeneric<T>(T t); 

通过你发布的代码的结构,好像你要前后做一些事来所有类型的ValueSpecific内容,所以你可以把私人PreValueGenericPostValueGeneric方法,所有的ValueGeneric重载致电的开始和结束,以避免过载之间的代码重复。

0

你有没有考虑使用的扩展方法为每种类型的?这可能是这种情况的替代方案。

你可以定义一个类,并定义方法。像:

namespace ExtensionMethods 
{ 
    public static class Class1 
    { 
     static void ValueSpecific(this string arg) 
     { 
      // do string stuff 
     } 
     static void ValueSpecific(this int arg) 
     { 
      // do int stuff 
     } 
    } 
} 

,然后,当你想使用它们,只是做

Int32 myIntVar = 20; 
myIntVar.ValueSpecific(); 
String myStringVar = "hi", 
myStringVar.ValueSpecific(); 

,你将不得不增加

using ExtensionMethods; 

只申报的方法和使用它们。

+1

一个有趣的想法,但不幸的是,在现实世界中,ValueSpecific方法不是静态的,它们是类的非静态方法。这可以通过一些沉重的重构来完成,但我认为它会变得更加不透明。 – Dave 2012-07-23 12:08:53

+0

是的,它们是静态的,但我认为这是一个有趣的发布作为替代。 – 2012-07-23 13:09:14