为什么在非泛型存在时选择通用方法?

ken*_*ken 8 c# generics overloading overload-resolution

下面的程序产生这个输出:

Foo<T> called

Process is terminated due to StackOverflowException.
Run Code Online (Sandbox Code Playgroud)

因此,Foo(baz)调用通用的Foo<T>,但Bar(baz)递归和并没有打电话Bar<T>.

我在C#5.0和Microsoft .NET上.当非泛型方法是一个时,编译器似乎选择泛型方法而不是递归override.

我在哪里可以找到这条规则的解释?(我猜想编译器会在两种情况下选择递归.)

以下是该计划的全部内容:

using System;

namespace ConsoleApplication1 {
    class Baz { }

    abstract class Parent {
        public abstract void Foo(Baz baz);
    }

    class Child : Parent {
        void Bar<T>(T baz) {
            Console.WriteLine("Bar<T> called");
        }

        public void Bar(Baz baz) {
            Bar(baz);
        }

        void Foo<T>(T baz) {
            Console.WriteLine("Foo<T> called");
        }

        public override void Foo(Baz baz) {
            Foo(baz);
        }
    }

    class Program {
        static void Main(string[] args) {
            var child = new Child();
            child.Foo(null);
            child.Bar(null);
            Console.ReadLine();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Nat*_*han 5

根据MSDN文档,优先考虑未被覆盖的方法签名.由于Foo的非泛型版本被覆盖,因此它会立即进入选择方法的优先级的底部.一般而言,下一步是选择最具体的方法并执行它.对于Bar方法,Bar(Baz baz)在您的情况下,该方法将始终是最具体的.

重载解析是一种编译时机制,用于在给定参数列表和一组候选函数成员的情况下选择要调用的最佳函数成员.重载决策选择要在C#中的以下不同上下文中调用的函数成员:

  • 调用invocation-expression中指定的方法(第7.5.5节).调用在object-creation-expression中命名的实例构造函数(第7.5.10.1节).
  • 通过元素访问调用索引器访问器(第7.5.6节).调用表达式中引用的预定义或用户定义的运算符(第7.2.3节和第7.2.4节).

这些上下文中的每一个都以其自己独特的方式定义候选函数成员集和参数列表,如上面列出的部分中详细描述的.例如,方法调用的候选集不包括标记为override的方法(第7.3节),如果派生类中的任何方法适用,则基类中的方法不是候选方法(第7.5.5.1节).

MSDN过载分辨率

我加粗了我认为与你的问题有关的文本.

这是关于Stack Overflow的另一个问题,可能会有所帮助.它总体上讨论了方法解决方案.不涉及重写方法,但有助于填写我没有触及的一些过程.