2010-05-04 186 views
9

這爲什麼有效?我不是抱怨,只是想知道。這是爲什麼工作?

void Test() 
{  
    int a = 1; 
    int b = 2; 

    What<int>(a, b); 
    // Why does this next line work? 
    What(a, b); 
} 

void What<T>(T a, T b) 
{ 

} 

回答

7

C#編譯器支持泛型的類型推斷,並且在使用var關鍵字時也很常見。

這裏int從上下文推斷(ab),所以不需要<int>。它使代碼更清晰並且有時更容易閱讀。

如果您讓編譯器推斷該類型,有時您的代碼可能會更清晰地閱讀,有時如果明確指定類型,則可能會更清楚。這是對你的情況的判斷。

+0

他沒有使用'var'關鍵字。 – SLaks 2010-05-04 13:42:29

+2

@SLaks:是的,我知道。 – 2010-05-04 13:43:46

+0

@SLaks:「'也''常見的' – Dykam 2010-05-04 13:46:31

5

編譯器根據您傳遞的實際參數的類型推斷泛型類型參數。

該功能使得LINQ調用更加簡單。 (你不需要寫numbers.Select<int, string>(i => i.ToString()),因爲編譯器推斷從numbersintstringToString

17

它的工作原理,因爲ab是整數,所以編譯器可以推斷出泛型類型參數爲What

在C#3中,即使類型不匹配,編譯器也可以推斷出類型參數,只要擴展轉換有意義即可。例如,如果clong,則What(a, c)將被解釋爲What<long>

請注意,如果說,如果cstring,它將無法正常工作。

+0

請注意,如果你有兩種不同的類型,它們都擴展了'Parent',並且你試圖做'What(a,b)'(其中a和b是這兩種不同類型),它不會推斷鍵入爲「Parent」。 – 2010-05-04 17:33:36

+1

@BlueRaja:這實際上是相同的情況,因爲在Dan的例子中int和string都是Object的擴展。這裏的設計原則是,當被要求找到一個集合中的「最好」成員時,C#總是從集合中選出一個成員。它從不從外面挑選一個成員。如果被問到{Tiger,Giraffe}最好的成員是什麼,它不會說「動物」,它說沒有最好的成員。 – 2010-05-04 19:34:49

1

編譯器是足夠聰明弄清楚,泛型類型爲「詮釋」

7

它使用的類型推斷泛型方法。請注意,這C#2和3之間改變。例如,這樣就不會出現在C#2的工作:

What("hello", new object()); 

...而它會在C#3(或4)。在C#2中,類型推斷是基於每個參數執行的,結果必須完全匹配。在C#3中,每個參數貢獻信息,然後放在一起來推斷類型參數。 C#3還支持多階段類型推斷,其中編譯器可以計算出一個類型參數,然後查看它是否有其他信息(例如由於帶有隱式參數類型的lambda表達式)。基本上它一直持續下去,直到它無法獲得更多信息,或者它完成 - 或者它看到矛盾的信息。 C#中的類型推斷並不像Hindley-Milner算法那麼強大,但它在其他方面效果更好(尤其是它總是能夠取得進展)。

有關更多信息,請參閱C#3規範的第7.4.2節。

2

編譯器可以推斷類型T爲int,因爲傳遞給What()的參數都是int類型的。您會注意到很多Linq擴展都是用泛型定義的(如IEnumerable),但通常以您展示的方式使用。