泛型:更好的匹配方法【翻譯】

來源:互聯網
上載者:User

原文地址: http://www.srtsolutions.com/generics-the-better-method-match?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+billwagner+%28Bill+Blogs+in+C%23%29

 

這個問題又出現在我參與分享的一個C#開發人員郵件清單中。因為還有這一主題的合理數量混亂,我想我會發布規則以及這些規則背後的原因。

 

這裡發布的所有東西都來自<<C#語言規範>>(第四版)  7.5.2節(類型引用) 和7.5.3節(重載解析).

 

考慮這兩個Log的重載方法:

    

static void Log<K,V>(K key, V value)
static void Log<K,V>(string key, IDictionary<K, V> values)

假如你調用下列代碼:

 

class FooDict : Dictionary<string, int>
{
}
// create custom dictionary
FooDict fooDict = new FooDict();
// should *not* use the IDictionary<K,V>
Log("FooDict", fooDict);
// try a regular dictionary value
Dictionary<string, int> dict = fooDict;
// should *not* use the IDictionary<K,V> 
Log("Dictionary", dict);
// now try the EXACT type
IDictionary<string, int> idict = fooDict;
// should use the IDictionary<K,V> - does
Log("IDictionary", idict);
 
注釋描述了代碼的調用執行情況,為什麼會有這樣的結果?
 
作任何操作執行之前,編譯器會先尋找所有合適的候選方法,那些候選方法可能包括泛型方法。如果方法調用不指定參數具體類型,編譯器就會推斷參數類型。Eric Lippert在說明的解釋已經很詳細了(如下)
類型推斷規則被設計成回答一個問題:僅給定實參和形式參數類型,什麼是最合適的實參被推斷成每個型別參數。
對於第一個重載方法,Log<string, FooDict>是推斷出最匹配的參數類型。現在分析下重載的運算規則,有兩個候選方法。使用類型推斷,第一個重載方法更匹配,因為調用第一個重載方法是確定轉換:Log<string, FooDict> 是一個來自於Log<string, FooDict>的確定轉換,調用第二個重載方法則是一個繼承轉換,Log<string, FooDict> 到Log<string, IDictionary<string, int>>的繼承轉換,因為FooDict類繼承IDictionary<string, int>介面。確定轉換優先於介面轉換。
同樣的處理邏輯可以應用於其它的繼承轉換:比如轉換成父類,長度轉換(如int類型轉成long類型)或者使用者定義類繼承轉換。
 
引用規範和說”就是這樣工作啟動並執行”是一樣的,但是為什麼這是正確的選擇對於程式設計語言來說呢?簡略地說,因為介面類型在真正編譯的時候類型轉換才起作用(注:泛型是產生後就已經起作用了)。 我完成的部分已經發布到這裡 C# Puzzlers Live Lessons。
 
 
以下是本人寫的完整的測試回合代碼
class Program
    {
        static void Main(string[] args)
        {
            // create custom dictionary
            FooDict fooDict = new FooDict();
            // should *not* use the IDictionary<K,V>
            Logger.Log("FooDict", fooDict);
            // try a regular dictionary value
            Dictionary<string, int> dict = fooDict;
            // should *not* use the IDictionary<K,V> 
            Logger.Log("Dictionary", dict);
            // now try the EXACT type
            IDictionary<string, int> idict = fooDict;
            // should use the IDictionary<K,V> - does
            Logger.Log("IDictionary", idict);
        }
    }
     class FooDict : Dictionary<string, int>
    {
    }
    class Logger
    { 
        public static void Log<K, V>(string key, IDictionary<K, V> values)
        {
            Console.WriteLine("call:Log<K, V>(string key, IDictionary<K, V> values)");
        }
        public static void Log<K, V>(K key, V value)
        {
            Console.WriteLine("call:Log<K,V>(K key, V value)");
        }
    }

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.