使用类型 C# 的方法重载
Posted
技术标签:
【中文标题】使用类型 C# 的方法重载【英文标题】:Method Overloading with Types C# 【发布时间】:2010-12-09 04:19:04 【问题描述】:我想知道以下是否可能。创建一个接受匿名类型(string、int、decimal、customObject 等)的类,然后具有基于 Type 执行不同操作的重载方法。示例
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();
这是可能的还是我只是在做梦?
【问题讨论】:
【参考方案1】:你想要做的可能是这样的:
class TestClass<T>
public string GetName<T>()
Type typeOfT = typeof(T);
if(typeOfT == typeof(string))
//do string stuff
虽然这是可能的,但你有点违背泛型的目的。泛型的意义在于类型无关,所以我认为泛型在这种情况下不合适。
【讨论】:
【参考方案2】:“专业化”在 C# 中不可能像在 C++ 中那样。在 .NET 泛型中,
我发现创建这样的通用接口或基类有时会有所帮助:
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;
【讨论】:
【参考方案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>()
【讨论】:
【参考方案4】:不,这是不可能的。您正在尝试做的类似于 C++ 中的模板专业化,这在 C# 中(遗憾地)是不可能的。
你需要 if/else 或打开
typeof(T)
调用专门的实现。
但是,您可以将 T 的类型限制为类(引用值)或结构(值)或某个基类的子类,如下所示:
public Foo<T> DoBar<T>() where T : FooBase;
【讨论】:
【参考方案5】:c# 不支持这种调度。
这也不是进行方法重载的正确方法(错误'TestClass'已经定义了一个具有相同参数类型的名为'GetName'的成员),只要所有内部不是方法签名的一部分。
【讨论】:
【参考方案6】:使用类扩展方法对你有用吗?
你基本上可以为你想要的类添加方法,然后你可以用同样的方式调用它。
namespace ExtensionMethods
public static class MyExtensions
public static int GetName(this String str)
...
调用使用:
myString.GetName();
【讨论】:
【参考方案7】:如果你需要在你的类中做特定类型的工作,那么你的类就不是通用的。您可能应该为要处理的每种类型创建一个单独的类。如果某些功能确实有适当的通用理由,您可以将其放在通用基类中。
一个例子:
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
【讨论】:
【参考方案8】:正如 BFree 提到的,您可以使用 if 树或更可能是 switch 语句来做到这一点,但在某些时候,您会希望您可以只编写方法并让 .Net 解决,尤其是如果您扩展了随着时间的推移过载。
解决方案是反射,尽管它在 .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 语句。
【讨论】:
以上是关于使用类型 C# 的方法重载的主要内容,如果未能解决你的问题,请参考以下文章