簡體   English   中英

多個方法重載匹配時的優先級是多少?

[英]What is the precedence when more than one method overload matches?

我正在嘗試了解C#中的OOP概念。

在以下示例代碼中:

  1. 為什么ins1更喜歡通用方法
  2. 為什么ins2ins3更喜歡非泛型方法

注意:當我注釋掉任何一個“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}");
        }
    }
}

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)
    }
}

在兩個調用中,兩個重載都是適用的函數成員。 在選擇要調用的重載時,編譯器首先檢查從參數類型(或表達式)到參數類型的轉換是“更好”。

當參數的類型是objectT被推斷為object ,因此對於兩個候選者,轉換是objectobject的身份轉換。 那時,涉及7.5.3.2的打破平局規則,第一個是:

如果M P是非通用方法並且M Q是通用方法,則M P優於M Q.

這就是為什么在這種情況下選擇非泛型重載的原因。

當參數是string類型時, T被推斷為string ,因此我們必須比較從stringstring的轉換(對於泛型方法)到從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 ,因此從字符串到字符串的轉換被認為更好 - 並且選擇了泛型方法。

為什么ins2,3更喜歡非泛型方法

因為在這兩種情況下, 變量類型 (不是實例化類型)都是J ,這與具有簽名MyTestMethod(J input)方法完全匹配。 因此,重載決策規則告訴它需要那個。

為什么ins1更喜歡通用方法

由於T可以是方法MyTestMethod(T input) where T : J J2MyTestMethod(T input) where T : J ,並且它可以強烈地將T類型設置為J2 ,再次,它是一個比基類J更好的匹配,來自您的其他方法。 所以它將方法與類型參數匹配。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM