Can*_*pus 3 c# generics overloading
我有这个例子C#代码:
class Stuff { } // empty class
void Main()
{
var list = new List<Stuff> {
new Stuff(),
new Stuff()
};
Fun(list);
}
void Fun<T>(List<T> a)
{
Debug.Log("called List<T> Fun");
foreach (T t in a) {
Fun(t);
}
}
void Fun(Stuff a)
{
Debug.Log("called Stuff Fun");
}
void Fun<T>(T a)
{
Debug.Log("called T Fun");
}
Run Code Online (Sandbox Code Playgroud)
调用Main()最终打印:
called List<T> Fun
called T Fun
called T Fun
Run Code Online (Sandbox Code Playgroud)
我不明白为什么编译器能够Fun<T>(List<T> a)按预期调用,但后来不知道调用Fun(Stuff a),哪个更具体Fun<T>(T a).在编译时是否确定T Stuff在这种情况下是肯定的?typeof(T)内部打印Fun<T>(List<T> a)按预期给出了"Stuff",但这并不能证明任何事情......
添加Fun(List<Stuff> a)方法是有效但不可取的(项目中的列表有很多不同的可能类型,并且所有这些行为应该是相同的).
我试过搜索这个问题,但无法用我能找到它的方式来表达它.对不起,如果之前有人问过这个问题(可能!).
Jon*_*eet 11
关键是要了解void Fun<T>(List<T> a)编译一次,重载解析执行一次.不是一次T,而是一次.
在编译此代码时考虑编译器的情况:
void Fun<T>(List<T> a)
{
Debug.Log("called List<T> fun");
foreach (T t in a) {
Fun(t);
}
}
Run Code Online (Sandbox Code Playgroud)
特别要考虑调用中的重载决策Fun(t).
编译器一无所知T,这是Fun(t)调用中参数的类型- 它可以是任何非指针类型.它必须在这些签名之间执行重载解析:
void Fun<T>(List<T> a)
void Fun(Stuff a)
void Fun<T>(T a)
Run Code Online (Sandbox Code Playgroud)
在只有这些方法是适用的一个是最后一个-的T调用代码被用作类型参数T中我们调用的方法,并且它的罚款.另外两种方法不适用,因为没有转换T为List<TList>(for any TList)或from Tto Stuff.
如果您希望在执行时执行重载决策,则可以使用动态类型:
foreach (dynamic d in a) {
Fun(d);
}
Run Code Online (Sandbox Code Playgroud)
我个人并不喜欢这样做,但在这种情况下它可能会做你想要的.另一方面,对于嵌套列表,它可能会变得棘手 - 如果你T是一个List<int>,那么你会期望它调用Fun<List<int>>(list)或Fun<int>(list)?老实说,我不记得规则,知道哪些是"更好"或是否含糊不清.