NOt*_*Dev 7 c# generics overloading
在使用带继承的泛型约束时,我遇到了一些令人惊讶的事情.我有一个Foo
与参数不同的重载方法- 基本或派生类实例.在这两种情况下,它通常只是将实例传递给第二对重载方法 - Bar
.
当我Foo
使用基类实例调用时,将调用基类的Bar
重载.当我Foo
使用派生类实例调用时,将调用派生类的Bar
重载.这是明确和预期的.
但是当我尝试将Foo
方法合并为GenericFoo
使用泛型和约束的单一方法时,方法的解析方式也不同 - T被正确解析,但只Bar
调用了基类重载.
public class Animal { }
public class Cat : Animal { }
public class AnimalProcessor
{
public static void Foo(Animal obj)
{
Console.WriteLine("Foo(Animal)");
Bar(obj);
}
public static void Foo(Cat obj)
{
Console.WriteLine("Foo(Cat)");
Bar(obj);
}
// new generic method to replace the two above
public static void GenericFoo<T>(T obj)
where T : Animal
{
Console.WriteLine("Foo(generic)");
Bar(obj);
}
public static void Bar(Animal obj)
{
Console.WriteLine("Bar(Animal)");
}
public static void Bar(Cat obj)
{
Console.WriteLine("Bar(Cat)");
}
}
Run Code Online (Sandbox Code Playgroud)
测试代码 - 非通用旧方法的两个第一种情况,新通用方法的两种情况.
Console.WriteLine("Animal()");
AnimalProcessor.Foo(new Animal());
Console.WriteLine();
Console.WriteLine("Cat()");
AnimalProcessor.Foo(new Cat());
Console.WriteLine();
Console.WriteLine("Animal()");
AnimalProcessor.GenericFoo(new Animal());
Console.WriteLine();
Console.WriteLine("Cat()");
AnimalProcessor.GenericFoo(new Cat());
Console.ReadLine();
Run Code Online (Sandbox Code Playgroud)
结果 - 请注意解决的类型差异Bar
:
Animal()
Foo(Animal)
Bar(Animal)
Cat()
Foo(Cat)
Bar(Cat)
Animal()
Foo(generic)
Bar(Animal)
Cat()
Foo(generic)
Bar(Animal)
Run Code Online (Sandbox Code Playgroud)
看起来编译器将所有调用绑定GenericFoo
到最不具体的重载,即使在编译时已知所有更具体类型的调用.为什么会这样,这种行为的原因是什么?哪部分规格定义了这个?
根据OP的要求,评论重新发布为答案:
泛型不是模板。通用方法编译一次,其行为适用于“最通用”的情况(在本例中为 Animal)。这与 C++ 样式模板不同,在 C++ 样式模板中,模板是按类型针对每个专业化单独编译的。