我只是想知道擴展方法如何連接到原始類。我知道在IL代碼中它調用了靜態方法,但它是如何做到的以及爲什麼不打破封裝。擴展方法如何掛接
擴展方法如何掛接
回答
擴展方法是通過將this
關鍵字在靜態方法中的第一個參數的前面指定的當編譯器看到該屬性時,它知道將擴展方法調用轉換爲適當的靜態方法調用,並將該實例作爲第一個參數傳遞。
由於調用只是普通的靜態方法調用,所以沒有機會破壞封裝;與所有靜態方法一樣,方法只能訪問擴展類型的公共接口。
他們不「掛鉤」。
Visaul Studio IDE通過在智能感知列表中顯示它,看起來就像它一樣。
編譯器「知道」如何處理引用,以便使用正確的參數進行正確的方法調用。
這簡直就是syntactic sugar - 這些方法只是靜態方法在單獨的靜態類上。使用this
修飾符可讓編譯器「知道」將ExtensionAttribute
添加到類中,以將其標記爲擴展方法。
由於擴展方法做不其實變化類,只能訪問其公共成員,封裝被保留。
從MSDN:
擴展方法是一種特殊的靜態方法,但他們被稱爲彷彿他們在擴展類型實例的方法。
(重點煤礦)
擴展方法只是語法糖,他們只是靜態方法。您只能訪問其中的公共字段或屬性,就像正常的靜態方法一樣。
public static void SomeExtension(this string s)
{
...
}
即用於與System.Runtime.CompilerServices.ExtensionAttribute裝飾方法只是語法糖:
[Extension]
public static void SomeExtension(string s)
{
...
}
關鍵因素是類的實例方法與靜態方法沒有根本的區別。只有一個小細節,他們有一個隱藏的論點。例如,String.IndexOf(char)的方法實際上是這樣的CLR:
public static int IndexOf(string thisRef, char value) {
// etc...
}
的thisRef說法是當你在代碼中使用這或訪問成員提供什麼樣的字符串引用的類。如你所見,這是一個從擴展方法到實例方法的小步驟。CLR不需要進行任何更改以支持該功能。
另一個微小的區別是,編譯器發出的代碼檢查這個對於實例方法是否爲空,但對於擴展方法不這樣做。您可以在空對象上調用擴展方法。雖然這可能看起來像一個功能,但它實際上是擴展方法引發的一個限制,實際上並不是該類的成員。
CLR在內部保留了類MethodTable的方法列表。擴展方法不在其中,從而阻止編譯器發出IL指令,它是用於獲取廉價空檢查的'技巧'。明確發出代碼以進行空檢查將是可能的,但他們選擇不這樣做。不太清楚爲什麼。
這樣做的另一個自動結果是擴展方法不能是虛擬的。
- 1. 擴展方法和接口
- 2. 接口的擴展方法
- 3. 擴展方法
- 4. 如何擴展擴展類的接口
- 5. AutoMapper展開擴展方法
- 6. 如何在Firefox擴展中掛接下載對話框?
- 7. 接口的擴展方法;代表
- 8. 通用擴展方法:接口
- 9. 擴展方法不適用於接口
- 10. C#中的鏈接擴展方法
- 11. 擴展類成員的擴展方法?
- 12. 使用擴展方法的擴展類
- 13. 擴展方法擴展靜態類
- 14. GraphicsPath.IsClockWise()擴展方法
- 15. C#擴展方法
- 16. 擴展方法ConvertAll
- 17. XElement.Elements()擴展方法?
- 18. 擴展類方法
- 19. VB.NET擴展方法
- 20. ValueProvider.GetValue擴展方法
- 21. 擴展方法2.10.8.1
- 22. C# - 擴展方法
- 23. C#擴展方法
- 24. 在擴展方法
- 25. 如何擴展WinForm的Dispose方法?
- 26. FirstOrDefault擴展方法如何工作?
- 27. 如何編譯擴展方法?
- 28. 如何改進我的擴展方法
- 29. 如何正確記錄擴展方法
- 30. 如何分組擴展方法?
+1好點:) – 2010-12-18 18:07:42