在使用带继承的泛型约束时,我遇到了一些非常令人惊讶的事情.我有一个重载的方法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)");
- }
- }
测试代码 – 非通用旧方法的两个第一种情况,新通用方法的两种情况.
- 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();
结果 – 注意Bar中解决的类型差异:
- Animal()
- Foo(Animal)
- Bar(Animal)
- Cat()
- Foo(Cat)
- Bar(Cat)
- Animal()
- Foo(generic)
- Bar(Animal)
- Cat()
- Foo(generic)
- Bar(Animal)
看起来编译器将所有来自GenericFoo的调用绑定到最不具体的重载,即使在编译时已知所有更具体类型的调用.为什么会这样,这种行为的原因是什么?哪部分规格定义了这个?