我正在使用包含泛型类中的以下重载方法的代码:
public class A<T>
{
public void Process(T item) { /*impl*/ }
public void Process(string item) { /*impl*/ }
}
当参数化string
的类时,我是否失去了使用泛型参数调用版本的可能性?
var a = new A<string>();
a.Process(""); //Always calls the non-generic Process(string)
答案 0 :(得分:14)
特定类型优先于泛型类型。
例如,这是我在LINQPad中测试过的。
void Main()
{
new A<string>().Process("Hello");
}
public class A<T>
{
public void Process(T item) { Console.WriteLine("T"); }
public void Process(string item) { Console.WriteLine("string"); }
}
// Output: string
如果您在隐藏通用方法时遇到问题,那么您需要重新考虑一些事情。通过重载具有特定类型的泛型方法,您实际上是在说“如果需要,请使用泛型重载,但如果可以,请使用特定版本,因为它应该知道什么是最好的。”
答案 1 :(得分:5)
是。这在C#规范第7.5.3节“重载解析”中有记录。
从7.5.3.6开始:
&#34;虽然声明的签名必须是唯一的,但类型参数的替换可能会产生相同的签名。在 在这种情况下,上面的超载解决方案的打破规则将会 选择最具体的成员。&#34;
在那里给出的例子表明,在下面的例子中,G<int>.F1
的重载分辨率将选择非泛型
class G1<U>
{
int F1(U u);
int F1(int i);
}
这里适用的打破平局规则在7.5.3.2中概述,&#34;更好的功能成员&#34;:
如果参数类型序列为{P1,P2,...,PN}和{Q1,Q2,..., QN}是等价的(即每个Pi都有一个身份转换为 相应的Qi),应用以下打破平局规则 命令,以确定更好的功能成员。
答案 2 :(得分:5)
我发现了一种方法,但它有点cross。。由于泛型和重载在构建时得到解决,因此您可以定义一个通用方法:
public static CallerClass
{
public static CallGenericOverload<T>(GenericClass<T> cls, T val)
{
return cls.ProblemOverload(val);
}
//We can also make an extension method.
//We don't have to of course, it's just more comfortable this way.
public static CallGenericOverloadExtension<T>(this GenericClass<T> cls, T val)
{
return cls.ProblemOverload(val);
}
}
public GenericClass<T>
{
public string ProblemOverload(T val)
{
return "ProblemOverload(T val)";
}
public string ProblemOverload(string val)
{
return "ProblemOverload(string val)";
}
}
现在,如果我们执行以下操作:
var genClass = new GenericClass<string>();
Console.WriteLine(genClass.ProblemOverload("")); //output: ProblemOverload(string val)
Console.WriteLine(CallerClass.CallGenericOverload(genClass, "")); //output: ProblemOverload(T val)
Console.WriteLine(genClass.CallGenericOverloadExtension("")); //output: ProblemOverload(T val)
如果定义泛型类而不是泛型方法,则可以使用类似的技巧。重要的是,您转移到ProblemOverload
的参数需要是T
类型而不是调用中的string
类型。毕竟,方法CallGenericOverload
知道它在构建时获得T
,因此它将绑定到接受参数的重载。它实际上会在运行时获得string
并不重要。
答案 3 :(得分:0)
之前做过这个,我倾向于说“不”,但总会有更多知识渊博的人反驳。
如果内存服务,运行时编译器选择执行最强类型的重载。
<强>澄清强>
我的答案措辞严厉,我应该得到downvote。
OP问道,“当参数化类的字符串时,我是否失去了使用泛型参数调用版本的可能性?”我没有回答“不,你不能这样做,“但是那个”不,你不会失去使用泛型参数调用版本的能力。“
我应该更清楚。