多个方法重载匹配时的优先级是多少?

Jaw*_*har 3 c# oop

我正在尝试了解C#中的OOP概念.

在以下示例代码中:

  1. 为什么ins1更喜欢通用方法
  2. 为什么ins2,ins3更喜欢非泛型方法

注意:当我注释掉任何一个"MyTestMethod"方法时,程序仍然会继续成功运行.这段代码不是来自制作的东西.这只是我的训练样本.所以,请不要介意命名约定和标准.

using System;

namespace ConsoleApplication1
{
    class Program
    {
        public static void MyTestMethod(J input)
        {
            Console.WriteLine($"Program.MyTestMethod: {input.Val}");
        }
        public static void MyTestMethod<T>(T input) where T : J
        {
            Console.WriteLine($"Program.MyTestMethod<T>: {input.Val}");
        }

        static void Main(string[] args)
        {
            J2 ins1 = new J2(1);
            MyTestMethod(ins1);

            J ins2 = new J(2);
            MyTestMethod(ins2);

            J ins3 = new J2(3);
            MyTestMethod(ins3);

            Console.ReadKey();
        }
    }
    internal class J
    {
        public int Val { get; set; }
        public J(int i)
        {
            Console.WriteLine($"concrete base {i}");
            Val = i;
        }
    }
    internal class J2 : J
    {
        public J2(int i) : base(i * -1)
        {
            Console.WriteLine($"concrete {i}");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 5

C#规范的第7.5.3.2节是这里的相关部分 - "更好的功能成员".

结果更简单地表现为:

using System;

class Test
{
    static void Foo<T>(T item)
    {
        Console.WriteLine("Generic");
    }

    static void Foo(object x)
    {
        Console.WriteLine("Non-generic");
    }

    static void Main()
    {
        Foo(new object()); // Calls Foo(object)
        Foo("test"); // Calls Foo<T>(T)
    }
}
Run Code Online (Sandbox Code Playgroud)

在两个调用中,两个重载都是适用的函数成员.在选择要调用的重载时,编译器首先检查从参数类型(或表达式)到参数类型的转换是"更好".

当参数的类型object,T被推断为object,以及,因此两个候选转换的标识转换objectobject.那时,涉及7.5.3.2的打破平局规则,第一个是:

如果M P是一个非泛型方法和M Q是一个通用的方法,则M P小于M好Q.

这就是为什么在这种情况下选择非泛型重载的原因.

当参数为类型的string,T被推断为string,所以我们必须转换从比较string,以string从(用于通用方法),以转换stringobject(对于非通用方法).这里引入了C#规范的第7.5.3.3节,其中包括:

给定从表达式E转换为类型T1的隐式转换C1,以及从表达式E转换为类型T2的隐式转换C2,如果以下至少一个成立,则C1是比C2更好的转换:

  • E具有类型S,并且存在从S到T 1而不是从S到T 2的标识转换

在这种情况下,E是表达式"test",S是类型string,T 1是类型string,T 2是类型object,因此从字符串到字符串的转换被认为更好 - 并且选择了泛型方法.