簡體   English   中英

C#編譯器如何與泛型一起使用?

[英]How does the C# compiler work with generics?

在C ++中, template聲明需要在頭文件中(除非您明確聲明模板類型),我明白了解原因。

我沒有得到的是如果C#編譯器沒有要檢查的.cs文件,它如何處理泛型。 我懷疑它會檢查CIL,因為這將是一個處理器密集型操作。 我知道它能夠從元數據中提取類型信息,但是如果通用函數的代碼也被編碼,那么對於可執行文件來說這將是一個巨大的膨脹。

那么,再次,編譯器如何使用泛型?

我想你問的是C#編譯器如何使用引用程序集中定義的泛型類型,而不是詢問C#編譯器如何編譯定義泛型類型的.cs文件(因為你說“如果它沒有.cs文件“)。

通用類型和成員在IL中編碼為通用。 封閉的泛型類型和成員由jit編譯器在運行時構造。 所以對你的問題的簡單回答是“C#編譯器通過發出IL來處理泛型類型,導致jit編譯器在運行時構造它們。”

C#編譯器從程序集中讀取有關類型的元數據,無需查看IL。 您可以使用反射編寫類似的代碼來分析泛型類型。

C#編譯器也沒有理由查看方法的內部實現。

請檢查C#和Java中的泛型和C ++中的模板之間有什么區別? 和類似的搜索結果 ,因為C#不需要知道方法的實現(與C ++不同) - C#中的所有約束都是從類/方法簽名中得知的,這與C ++模板不同,其中類型只需要匹配body內使用的方法的名稱。

讓我試着清理一下......

泛型存儲為IL,包括元數據中的參數和約束。 泛型類型也是類型,它們在運行時轉換為運行時類型。 這是與C ++的主要區別,其中模板類型不存在,但只有派生類型; 在C#中,泛型類型存在於DLL中,但派生類型不存在(直到它們在運行時創建)。

但是,編譯器確實做了一些事情。 例如,如果你有一個List.Add(T),那么IL中的簽名就是那個。 但是,如果您調用它,它將使用List.Add(Foo)作為方法解析方法。 例如,在您的IL中,它將顯示類似的內容(加載字段時):

ldfld class [mscorlib]System.List`1<Foo> Bar::variable

請注意,'Foo'在這里,而不是'T'。

此外,如果在泛型定義中對T進行約束,則會根據元數據檢查它們的編譯時間。

在這一點上,我想指出一些完全不同但相關的東西。 C#通過延遲生成類型(通常)獲得性能。 這與C ++也有很大不同。 如果您嘗試使用靜態構造函數以及何時調用它們,您可以看到這一點。

暫無
暫無

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

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