這爲什麼有效?我不是抱怨,只是想知道。這是爲什麼工作?
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)
{
}
這爲什麼有效?我不是抱怨,只是想知道。這是爲什麼工作?
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)
{
}
C#編譯器支持泛型的類型推斷,並且在使用var關鍵字時也很常見。
這裏int
從上下文推斷(a
和b
),所以不需要<int>
。它使代碼更清晰並且有時更容易閱讀。
如果您讓編譯器推斷該類型,有時您的代碼可能會更清晰地閱讀,有時如果明確指定類型,則可能會更清楚。這是對你的情況的判斷。
編譯器根據您傳遞的實際參數的類型推斷泛型類型參數。
該功能使得LINQ調用更加簡單。 (你不需要寫numbers.Select<int, string>(i => i.ToString())
,因爲編譯器推斷從numbers
的int
和string
從ToString
)
它的工作原理,因爲a
和b
是整數,所以編譯器可以推斷出泛型類型參數爲What
。
在C#3中,即使類型不匹配,編譯器也可以推斷出類型參數,只要擴展轉換有意義即可。例如,如果c
是long
,則What(a, c)
將被解釋爲What<long>
。
請注意,如果說,如果c
是string
,它將無法正常工作。
請注意,如果你有兩種不同的類型,它們都擴展了'Parent',並且你試圖做'What(a,b)'(其中a和b是這兩種不同類型),它不會推斷鍵入爲「Parent」。 – 2010-05-04 17:33:36
@BlueRaja:這實際上是相同的情況,因爲在Dan的例子中int和string都是Object的擴展。這裏的設計原則是,當被要求找到一個集合中的「最好」成員時,C#總是從集合中選出一個成員。它從不從外面挑選一個成員。如果被問到{Tiger,Giraffe}最好的成員是什麼,它不會說「動物」,它說沒有最好的成員。 – 2010-05-04 19:34:49
編譯器是足夠聰明弄清楚,泛型類型爲「詮釋」
它使用的類型推斷泛型方法。請注意,這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節。
編譯器可以推斷類型T爲int,因爲傳遞給What()的參數都是int類型的。您會注意到很多Linq擴展都是用泛型定義的(如IEnumerable),但通常以您展示的方式使用。
如果在C#3中這是如何工作的主題。0對你來說很有意思,這裏有一段我從2006年開始解釋它的視頻,當時我們首先爲C#3.0設計了這個功能的版本。
http://blogs.msdn.com/ericlippert/archive/2006/11/17/a-face-made-for-email-part-three.aspx
參見我的博客的 「類型推理」 部分:
http://blogs.msdn.com/ericlippert/archive/tags/Type+Inference/default.aspx
他沒有使用'var'關鍵字。 – SLaks 2010-05-04 13:42:29
@SLaks:是的,我知道。 – 2010-05-04 13:43:46
@SLaks:「'也''常見的' – Dykam 2010-05-04 13:46:31