可收集的元件 是可以卸除的動態元件,而不需要卸除其建立所在的應用程式域。 可收集元件所使用的所有受管理和未受管理記憶體及其中的類型都可以回收。 元件名稱等資訊會從內部數據表中移除。
若要啟用卸載,請在建立動態元件時使用 AssemblyBuilderAccess.RunAndCollect 旗標。 元件是暫時性的(也就是無法儲存),而且受限於 可收集元件的限制 一節中所述的限制。 當您釋放與組件相關聯的所有物件時,通用語言執行平台(CLR)會自動卸載可收集的組件。 在所有其他方面,可收集的元件會以與其他動態元件相同的方式建立及使用。
可收集元件的存留期
可回收組件的存留期是由其所包含的類型的參考和從這些類型創建的物件的存在所控制。 共通語言執行平台不會移除組件,只要有下列一或多個項目存在(T 是組件中定義的任何類型):
T的實例。T的陣列實例。泛型型別的實例,其具有
T其中一個型別自變數。 這包括泛型集合T,即使該集合是空的。代表Type的TypeBuilder或
T實例。這很重要
您必須釋放代表組件部分的所有物件。 ModuleBuilder 定義
T保留對 TypeBuilder 的引用,而 AssemblyBuilder 物件保留對 ModuleBuilder 的引用,因此必須釋放這些物件的引用。 在建構LocalBuilder中使用的ILGenerator或T防止卸載。由另一個動態定義的型別
T所指向的靜態參考T1,仍然可以通過執行程式碼來觸及到。 例如,T1可能衍生自T,或T可能是方法T1中的參數類型。指向
ByRef之靜態欄位的T。RuntimeTypeHandle、RuntimeFieldHandle 或 RuntimeMethodHandle 指向
T或T的元件。能間接或直接用來存取代表 Type 的
T物件的任何反射物件的實例。 例如,可以從元素類型為 Type 的陣列類型中取得T物件,或從具有T作為類型引數的泛型型別中取得T。任何線程的呼叫堆疊中的方法
M,其方法M是T的方法或在組件中定義的模組層級方法。委派給元件模組中定義的靜態方法。
如果在此清單中只有一項專案存在於組件中的某種類型或方法,運行時便無法卸載該組件。
備註
執行階段實際上不會卸除元件,直到清單中所有項目的終結器已執行完畢為止。
為了追蹤存留期的目的,建構的泛型型別,例如 List<int> (在 C#) 或 List(Of Integer) (在 Visual Basic 中)建立並用於產生可收集元件時,會被視為已定義於包含泛型型別定義的元件中,或在包含其中一個類型自變數定義的元件中定義。 所使用的確切組件是實作細節,而且可能會改變。
可收集元件的限制措施
下列限制適用於可收集的元件:
靜態參考
普通動態組件中的類型不能有靜態參考指向可收集的組件中定義的類型。 例如,如果您定義了一個繼承自可收集元件中型別的普通型別,則會拋出NotSupportedException例外狀況。 可收集元件中的類型可以有另一個可收集元件中型別的靜態參考,但這會將參考元件的存留期延長至參考元件的存留期。
下列限制適用於 .NET Framework 中的可收集元件:
COM Interop
無法定義可收集元件內的 COM 介面,而且無法將可收集元件內的類型實例轉換成 COM 物件。 可收集組件中的類型不能用作 COM 可呼叫包裝器(CCW)或運行時可呼叫包裝器(RCW)。 不過,可收集元件中的類型可以使用實作了 COM 介面的物件。
平台調用
具有 DllImportAttribute 屬性的方法在可收集元件中宣告時,無法編譯。 指令 OpCodes.Calli 不能用於可收集的組件中型別的實作中,而且此型別無法封送至非受管程式碼。 不過,您可以使用不可收集元件中宣告的進入點來呼叫原生程序代碼。
編組
定義在可收集元件中的物件(特別是委派)無法進行封送處理。 這是所有瞬時發出類型的限制。
元件載入
唯一支援載入可收集組件的機制是反射發射。 您無法卸載透過其他形式載入的組件。
內容系結物件
不支援內容靜態變數。 集合式元件中的類型無法繼承 ContextBoundObject。 不過,集合性組件中的程式碼可以使用在其他位置定義的內容系結物件。
線程靜態數據
不支援線程靜態變數。
下列限制適用於 .NET Framework 和 .NET 9 之前的 .NET 版本中的可收集元件:
具有的靜態欄位
FixedAddressValueTypeAttribute可收集組件中定義的靜態欄位無法套用FixedAddressValueTypeAttribute屬性。