2009-10-22 73 views
10

我想知道以下是否可能。创建一个接受匿名类型(string,int,decimal,customObject等)的类,然后重载基于类型执行不同操作的方法。例如方法重载类型C#

class TestClass<T> 
{ 
    public void GetName<string>() 
    { 
     //do work knowing that the type is a string  
    } 

    public string GetName<int>() 
    { 
     //do work knowing that the type is an int 

    } 

    public string GetName<int>(int addNumber) 
    { 
     //do work knowing that the type is an int (overloaded)  
    } 

    public string GetName<DateTime>() 
    { 
     //do work knowing that the type is a DateTime 

    } 

    public string GetName<customObject>() 
    { 
     //do work knowing that the type is a customObject type  
    } 

} 

所以,现在我可以调用GetName方法,因为我已经在类型过去了我初始化的对象,正确的方法是发现和执行。

TestClass foo = new TestClass<int>(); 

//executes the second method because that's the only one with a "int" type 
foo.GetName(); 

这是可能的还是我只是在做梦?

回答

12

你试图做的是可能是这样的:

class TestClass<T> 
{ 
    public string GetName<T>() 
    { 
     Type typeOfT = typeof(T); 
     if(typeOfT == typeof(string)) 
     { 
      //do string stuff 
     } 
    } 
} 

虽然这可能的,你是那种击败仿制药的目的。泛型的一点是当型不是的问题时,所以我不认为泛型在这种情况下是合适的。

0

会使用类扩展方法吗?

你基本上可以将方法添加到你想要的类,然后你可以用同样的方法调用它。

namespace ExtensionMethods 
{ 
    public static class MyExtensions 
    { 
     public static int GetName(this String str) 
     { 
      ... 
     } 
    } 
} 

使用称为:

myString.GetName(); 
4

“专业化”,在C#是不可能的它是在C++的方式。在.NET泛型中,对于T的所有可能值,通用类或方法<T>必须相同。这允许运行时执行两种不同参考类型的优化,例如TestClass <字符串>和TestClass <列表<int> >,共享相同的机器语言代码。 (不同的值类型获得单独的机器代码,但你仍然无法专注。)

我发现它有时帮助创建一个通用的接口或基类是这样的:

abstract class Base<T> { 
    public abstract T GetName(); 
    // any common code goes here that does not require specialization 
} 

而且在衍生做到专业化类别:

class IntVersion : Base<int> { 
    public override int GetName() { return 1; } 
    public int GetName(int addNumber) { ... } 
} 
class StringVersion : Base<string> { 
    public override string GetName() { return "foo"; } 
} 
class DateTimeVersion : Base<DateTime> { 
    public override DateTime GetName() { return DateTime.Now; } 
} 
+0

+1 Generics!=模板 – user7116 2009-10-22 17:11:56

1

不,这是不可能的。你想要做的是类似于C++中的模板专门化,这在C#中(可惜)是不可能的。

你需要

typeof(T) 

到的if/else或开关来调用特定的实现。

但是,可以约束T的类型为一个类(基准值)或结构(值)或特定基类的子类,像这样:

public Foo<T> DoBar<T>() where T : FooBase; 
0

C#不具有用于支撑这种调度。

只要<>内部不是方法签名的一部分,这也是做方法重载的不正确方法(Error'TestClass'已经定义了一个名为'GetName'的成员具有相同的参数类型)。

3

专业化在C#中是不可能的。在C#中最接近的东西是以下内容

public void Example() { 
    public static void Method<T>(T value) { ... } 
    public static void Method(int value){ ... } 
    public static void Method(string) { ... } 
} 

C#编译器将优先于通用方法的非泛型方法。这意味着使用int参数进行调用将绑定到int重载与通用重载之间。

Example.Method(42); // Method(int) 
Example.Method(new Class1()) // Method<T>(T) 

这会咬你,因为这种方法一般称为不适用。在这种情况下,无论类型如何,它都会绑定到泛型重载。

public void Gotcha<T>(T value) { 
    Example.Method(value); 
} 

Gotcha(42); // Still calls Example.Method<T>() 
0

如果你需要在你的类中做类型特定的工作,那么你的类不是通用的。你应该为每个你想要处理的类型创建一个单独的类。如果某些功能确实具有通用的理由,那么可以将它放在通用的基类中。

一个例子:

abstract class TestClass<T> 
{ 
    public List<T> Items { get; set; } 

    // other generic (i.e. non type-specific) code 
} 

class IntTestClass : TestClass<int> 
{ 
    public string GetName() 
    { 
     // do work knowing that the type is an int 
    } 

    // other code specific to the int case 
} 

class StringTestClass : TestClass<string> 
{ 
    public string GetName() 
    { 
     // do work knowing that the type is a string 
    } 

    // other code specific to the string case 
} 
0

由于贝丽提到的,你可以,如果树,或者更可能的switch语句有做到这一点,但在某些时候你会希望你可以只写方法,让净弄明白,特别是如果你随着时间的推移增长超负荷库。

的解决方案有反映,虽然它是相当便宜的性能代价在.net:

using System.Reflection; 
... 

public string DoSomething(object val) 
{ 
    // Force the concrete type 
    var typeArgs = new Type[] { val.GetType() }; 

    // Avoid hard-coding the overloaded method name 
    string methodName = new Func<string, string>(GetName).Method.Name; 

    // Use BindingFlags.NonPublic instead of Public, if protected or private 
    var bindingFlags = BindingFlags.Public | BindingFlags.Instance; 

    var method = this.GetType().GetMethod(
     methodName, bindingFlags, null, typeArgs, null); 

    string s = (string)method.Invoke(this, new object[] { val }); 

    return s; 
} 

你基本上只是告诉了思考框架去做到这一点switch语句你。