標籤:blog 使用 io for 代碼 div ar line
擴充方法被定義為靜態方法,但它們是通過執行個體方法文法進行調用的。 它們的第一個參數指定該方法作用於哪個類型,並且該參數以 this 修飾符為首碼。 僅當你使用 using 指令將命名空間顯式匯入到原始碼中之後,擴充方法才位於範圍中。下面的樣本示範為 SystemString 類定義的一個擴充方法。 請注意,它是在非嵌套的、非泛型靜態類內部定義的:namespace ExtensionMethods { public static class MyExtensions { public static int WordCount(this String str) { return str.Split(new char[] { ‘ ‘, ‘.‘, ‘?‘ }, StringSplitOptions.RemoveEmptyEntries).Length; } } } 可使用此 using 指令將WordCount擴充方法置於範圍中:using ExtensionMethods;而且,可以使用以下文法從應用程式中調用該擴充方法:string s = "Hello Extension Methods";int i = s.WordCount();在代碼中,可以使用執行個體方法文法調用該擴充方法。 但是,編譯器產生的中繼語言 (IL) 會將代碼轉換為對靜態方法的調用。 因此,並未真正違反封裝原則。 實際上,擴充方法無法訪問它們所擴充的類型中的私人變數。
通常,你更多時候是調用擴充方法而不是實現你自己的擴充方法。 由於擴充方法是使用執行個體方法文法調用的,因此不需要任何特殊知識即可從用戶端代碼中使用它們。 若要為特定類型啟用擴充方法,只需為在其中定義這些方法的命名空間添加 using 指令。 例如,若要使用標準查詢運算子,請將此 using 指令添加到代碼中:
可以使用擴充方法來擴充類或介面,但不能重寫擴充方法。 與介面或類方法具有相同名稱和簽名的擴充方法永遠不會被調用。 編譯時間,擴充方法的優先順序總是比類型本身中定義的執行個體方法低。 換句話說,如果某個類型具有一個名為Process(int i)的方法,而你有一個具有相同簽名的擴充方法,則編譯器總是綁定到該執行個體方法。 當編譯器遇到方法調用時,它首先在該類型的執行個體方法中尋找匹配的方法。 如果未找到任何匹配方法,編譯器將搜尋為該類型定義的任何擴充方法,並且綁定到它找到的第一個擴充方法。 下面的樣本示範編譯器如何確定要綁定到哪個擴充方法或執行個體方法。
namespace DefineIMyInterface { using System; public interface IMyInterface { // Any class that implements IMyInterface must define a method // that matches the following signature. void MethodB(); } } // Define extension methods for IMyInterface. namespace Extensions { using System; using DefineIMyInterface; // The following extension methods can be accessed by instances of any // class that implements IMyInterface. public static class Extension { public static void MethodA(this IMyInterface myInterface, int i) { Console.WriteLine ("Extension.MethodA(this IMyInterface myInterface, int i)"); } public static void MethodA(this IMyInterface myInterface, string s) { Console.WriteLine ("Extension.MethodA(this IMyInterface myInterface, string s)"); } // This method is never called in ExtensionMethodsDemo1, because each // of the three classes A, B, and C implements a method named MethodB // that has a matching signature. public static void MethodB(this IMyInterface myInterface) { Console.WriteLine ("Extension.MethodB(this IMyInterface myInterface)"); } } } // Define three classes that implement IMyInterface, and then use them to test // the extension methods. namespace ExtensionMethodsDemo1 { using System; using Extensions; using DefineIMyInterface; class A : IMyInterface { public void MethodB() { Console.WriteLine("A.MethodB()"); } } class B : IMyInterface { public void MethodB() { Console.WriteLine("B.MethodB()"); } public void MethodA(int i) { Console.WriteLine("B.MethodA(int i)"); } } class C : IMyInterface { public void MethodB() { Console.WriteLine("C.MethodB()"); } public void MethodA(object obj) { Console.WriteLine("C.MethodA(object obj)"); } } class ExtMethodDemo { static void Main(string[] args) { // Declare an instance of class A, class B, and class C. A a = new A(); B b = new B(); C c = new C(); // For a, b, and c, call the following methods: // -- MethodA with an int argument // -- MethodA with a string argument // -- MethodB with no argument. // A contains no MethodA, so each call to MethodA resolves to // the extension method that has a matching signature. a.MethodA(1); // Extension.MethodA(object, int) a.MethodA("hello"); // Extension.MethodA(object, string) // A has a method that matches the signature of the following call // to MethodB. a.MethodB(); // A.MethodB() // B has methods that match the signatures of the following // method calls. b.MethodA(1); // B.MethodA(int) b.MethodB(); // B.MethodB() // B has no matching method for the following call, but // class Extension does. b.MethodA("hello"); // Extension.MethodA(object, string) // C contains an instance method that matches each of the following // method calls. c.MethodA(1); // C.MethodA(object) c.MethodA("hello"); // C.MethodA(object) c.MethodB(); // C.MethodB() } } } /* Output: Extension.MethodA(this IMyInterface myInterface, int i) Extension.MethodA(this IMyInterface myInterface, string s) A.MethodB() B.MethodA(int i) B.MethodB() Extension.MethodA(this IMyInterface myInterface, string s) C.MethodA(object obj) C.MethodA(object obj) C.MethodB() */