2012-01-28 225 views
5

我是堆棧溢出的一個newby,所以請在我身上輕鬆一下!我正在深入閱讀C#,但我遇到了一個我不相信的場景。對網絡的快速搜索也沒有發現任何結果。泛型方法的類型參數的類型推斷

說我定義以下重載方法:

void AreEqual<T>(T expected, T actual) 

void AreEqual(object expected, object actual) 

如果我打電話AreEqual()沒有指定類型參數:

AreEqual("Hello", "Hello") 

調用該方法的通用或非通用版本?泛型方法是在推斷出類型參數的情況下調用的,還是調用方法參數隱式轉換爲System.Object的非泛型方法?

我希望我的問題很清楚。提前感謝您的任何建議。

+5

你當然可以寫一些簡單的代碼來檢查這個... – 2012-01-28 01:43:21

+1

http://blogs.msdn.com/b/ericlippert/archive/2009/07/30/generics-are-not-templates.aspx – 2012-01-28 01:56:51

+0

@米奇麥 - 真實的,但我不會做我的第一篇文章。它對其他人在這裏看到答案很有用。 – zekesteer 2012-01-28 02:01:51

回答

5

該仿製藥可以生成功能AreEqual(string, string)。這比AreEqual(object, object)更接近匹配,因此選擇通用函數。

有趣的是,即使編譯器會導致約束違規錯誤,編譯器也會選擇這個通用函數。

請看下面的例子:

using System.Diagnostics; 

namespace ConsoleSandbox 
{ 
    interface IBar 
    { 
    } 

    class Program 
    { 
     static void Foo<T>(T obj1) where T: IBar 
     { 
      Trace.WriteLine("Inside Foo<T>"); 
     } 


     static void Foo(object obj) 
     { 
      Trace.WriteLine("Inside Foo Object"); 
     } 

     static void Main(string[] args) 
     { 

      Foo("Hello"); 
     } 
    } 
} 

即使在這裏,會選擇在非通用版本的通用版本。然後你得到這個錯誤:

The type 'string' cannot be used as type parameter 'T' in the generic type or method 'ConsoleSandbox.Program.Foo(T)'. There is no implicit reference conversion from 'string' to 'ConsoleSandbox.IBar'.

但如果添加了一個功能Foo(string obj1)它會工作。

+0

很好的答案,謝謝!很好的例子,我自己試了一下,以確認:-) – zekesteer 2012-01-28 01:58:12

+0

請注意,重載解析是由C#編譯器完成的,而不是.NET框架。 – phoog 2012-01-28 03:58:53

+0

@phoog - 謝謝,我已經改變了措辭 – 2012-01-28 04:31:55