我想知道以下是否可行。创建一个接受匿名类型(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();
这可能还是我只是在做梦?
答案 0 :(得分:12)
你想要做的事情是这样的:
class TestClass<T>
{
public string GetName<T>()
{
Type typeOfT = typeof(T);
if(typeOfT == typeof(string))
{
//do string stuff
}
}
}
虽然可能,但你有点打败了泛型的目的。泛型的关键是当类型>>不重要时,所以在这种情况下我不认为泛型是合适的。
答案 1 :(得分:4)
C#中的“专业化”在C ++中是不可能的。在.NET泛型中,&lt; T&gt;的泛型类或方法。对于T的所有可能值,它必须相同。这允许运行时进行两种不同引用类型的优化,比如TestClass&lt; string&gt;和TestClass&lt; List&lt; int&gt;&gt;,共享相同的机器语言代码。 (不同的值类型获得单独的机器代码,但您仍然无法专门化。)
我发现创建一个通用接口或基类有时会有所帮助:
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; }
}
答案 2 :(得分:4)
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>()
答案 3 :(得分:1)
不,这是不可能的。你要做的是类似于C ++中的模板专业化,(遗憾的是)在C#中是不可能的。
你需要if / else或开启
typeof(T)
调用专门的实现。
但是,您可以将T的类型约束为类(引用值)或结构(值)或某个基类的子类,如下所示:
public Foo<T> DoBar<T>() where T : FooBase;
答案 4 :(得分:0)
使用类扩展方法会对你有用吗?
您实际上可以将方法添加到所需的类中,然后您可以以相同的方式调用它。
namespace ExtensionMethods
{
public static class MyExtensions
{
public static int GetName(this String str)
{
...
}
}
}
使用:
调用myString.GetName();
答案 5 :(得分:0)
c#不支持此类调度。
这也不是正确进行方法重载的方法(Error'TestClass'已经定义了一个名为'GetName'且具有相同参数类型的成员),只要所有内部&lt;&gt;不是方法签名的一部分。
答案 6 :(得分: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
}
答案 7 :(得分:0)
正如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;
}
你基本上只是告诉Reflection框架为你做那个switch语句。