Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ajax/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当多个方法重载匹配时,优先级是多少?_C#_Oop - Fatal编程技术网

C# 当多个方法重载匹配时,优先级是多少?

C# 当多个方法重载匹配时,优先级是多少?,c#,oop,C#,Oop,我正在努力理解C#中的OOP概念 在以下示例代码中: 为什么ins1更喜欢通用方法 为什么ins2,ins3更喜欢非通用方法 注意:当我注释掉任何一个“MyTestMethod”方法时,程序仍然会继续成功运行。此代码段不是生产中的内容。这只是我的训练样本。因此,请不要介意命名约定和标准 using System; namespace ConsoleApplication1 { class Program { public static void MyTestMe

我正在努力理解C#中的OOP概念

在以下示例代码中:

  • 为什么
    ins1
    更喜欢通用方法
  • 为什么
    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}");
            }
        }
    }
    
    使用系统;
    命名空间控制台应用程序1
    {
    班级计划
    {
    公共静态void MyTestMethod(J输入)
    {
    Console.WriteLine($“Program.MyTestMethod:{input.Val}”);
    }
    公共静态void MyTestMethod(T输入),其中T:J
    {
    Console.WriteLine($“Program.MyTestMethod:{input.Val}”);
    }
    静态void Main(字符串[]参数)
    {
    J2 ins1=新的J2(1);
    MyTestMethod(ins1);
    J ins2=新的J(2);
    MyTestMethod(ins2);
    J ins3=新的J2(3);
    MyTestMethod(ins3);
    Console.ReadKey();
    }
    }
    内部类别J
    {
    公共int Val{get;set;}
    公共J(国际一)
    {
    Console.WriteLine($“混凝土基层{i}”);
    Val=i;
    }
    }
    内部类别J2:J
    {
    公共J2(内部i):基础(i*-1)
    {
    Console.WriteLine($“concrete{i}”);
    }
    }
    }
    
    为什么ins2,3更喜欢非泛型方法

    因为在这两种情况下,变量的类型(不是实例化类型)都是
    J
    ,这与签名为
    MyTestMethod(J input)
    的方法完全匹配。因此,重载解析规则告诉它采用该规则

    为什么ins1更喜欢通用方法

    由于
    T
    可以在方法
    MyTestMethod(T输入)中
    J2
    ,其中T:J
    ,并且它可以强式键入
    T
    J2
    ,同样,它比其他方法的基类
    J
    更匹配。因此,它将方法与类型参数相匹配。

    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)
        }
    }
    
    使用系统;
    课堂测试
    {
    静态无效Foo(T项)
    {
    Console.WriteLine(“通用”);
    }
    静态void Foo(对象x)
    {
    Console.WriteLine(“非通用”);
    }
    静态void Main()
    {
    Foo(新对象());//调用Foo(对象)
    Foo(“test”);//调用Foo(T)
    }
    }
    
    在这两个调用中,两个重载都是适用的函数成员。在选择要调用的重载时,编译器首先检查从参数类型(或表达式)到参数类型的转换是否“更好”

    当参数的类型为
    object
    时,
    T
    也被推断为
    object
    ,因此对于这两个候选者,转换是
    object
    object
    的身份转换。在这一点上,7.5.3.2中的打破平局规则就涉及到了,第一个规则是:

    如果MP是非泛型方法,而MQ是泛型方法,则MP优于MQ

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

    当参数类型为
    string
    时,
    T
    被推断为
    string
    ,因此我们必须比较从
    string
    string
    的转换(对于泛型方法)到从
    string
    object
    (对于非泛型方法)的转换。本规范第7.5.3.3节从以下内容开始:

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

    • E有一个类型S,存在从S到T1的标识转换,但不存在从S到T2的标识转换

    在此上下文中,E是表达式“test”,S是类型
    string
    ,T1是类型
    string
    ,T2是类型
    object
    ,因此从string到string的转换被认为更好,并且选择了泛型方法。

    您的代码根本没有任何泛型方法。@Jon现在有了。OP使用了
    ,它隐藏了可以解释为HTML标记的内容,例如
    。请注意在以后开始时发布编译的代码,检查预览以确保它确实是您想要的代码。(一般来说,使用标记格式而不是HTML…@AntonGogolev:这个版本没有帮助,因为它是前泛型。我会直接进入真正的C#规范——不容易通过章节超链接,但可以让你下载wohle的东西。这是C#6.0@AntonGogolevYepp,速度很快(落后几秒钟,所以我自己没有回答)。补充答案。我认为,对于问题创建者来说,最好的读物是:它描述了“where(generic type constraint)”在c#中的工作方式。感谢@Thomas提供的有用评论。有相当多的关于方法优先级的资源确实对阅读很有用。泛型类型约束在这里并不真正相关——它在重载解析中不起作用。只有在重载解析选择了要使用的重载后,才会应用它来验证结果。(在本例中,这并不重要,因为两种方法都可以处理所有调用。)好的,同意。精确匹配总是赢。我的回答有错吗@JonSkeetNeh,我们不可能都是你…:)@JonSkeet希望更新是正确的。