當(dāng)方法的第一個(gè)形參包含 this 修飾符時(shí),稱該方法為擴(kuò)展方法 (extension method)。只能在非泛型、非嵌套靜態(tài)類中聲明擴(kuò)展方法。擴(kuò)展方法的第一個(gè)形參不能帶有除 this 之外的其他修飾符,而且形參類型不能是指針類型。下面是一個(gè)聲明兩個(gè)擴(kuò)展方法的靜態(tài)類的示例:
1 public static class Extensions2 {3 public static int ToInt32(this string s) {4 return Int32.Parse(s);5 }6 public static T[] Slice<T>(this T[] source, int index, int count) {7 if (index < 0 || count < 0 || source.Length – index < count)8 throw new ArgumentException();9 T[] result = new T[count];10 Array.Copy(source, index, result, 0, count);11 return result;12 }13 }14 ![]() 擴(kuò)展方法是常規(guī)靜態(tài)方法。另外,如果它的包容靜態(tài)類在范圍之內(nèi),則可以使用實(shí)例方法調(diào)用語(yǔ)法 來(lái)調(diào)用擴(kuò)展方法,同時(shí)將接收器表達(dá)式用作第一個(gè)實(shí)參。下面的程序使用上面聲明的擴(kuò)展方法:
1 static class Program2 {3 static void Main() {4 string[] strings = { "1", "22", "333", "4444" };5 foreach (string s in strings.Slice(1, 2)) {6 Console.WriteLine(s.ToInt32());7 }8 }9 }10 ![]() Slice 方法在 string[] 上可用,ToInt32 方法在字符串上可用,原因是它們都已聲明為擴(kuò)展方法。該程序的含義與下面使用普通靜態(tài)方法調(diào)用的程序相同:1 static class Program2 {3 static void Main() {4 string[] strings = { "1", "22", "333", "4444" };5 foreach (string s in Extensions.Slice(strings, 1, 2)) {6 Console.WriteLine(Extensions.ToInt32(s));7 }8 }9 }10 ![]()
· C 為非泛型、非嵌套類 · M 的名稱為和用戶調(diào)用方法名稱相同 · M 作為靜態(tài)方法應(yīng)用于參數(shù)時(shí)是可訪問(wèn)且適用的 存在從表倒是到方法M 的第一個(gè)參數(shù)的類型的隱式標(biāo)識(shí)、引用或裝箱轉(zhuǎn)換。 · 從最接近的封閉命名空間聲明開始,接下來(lái)是每個(gè)封閉命名空間聲明,最后是包含編譯單元,搜索將連續(xù)進(jìn)行以找到候選的擴(kuò)展方法集: o 如果給定的命名空間或編譯單元直接包含具有適當(dāng)擴(kuò)展方法M的非泛型類型聲明C,則這些擴(kuò)展方法的集合為候選集。 o 如果使用給定命名空間或編譯單元中的命名空間指令導(dǎo)入的命名空間直接包含具有適當(dāng)擴(kuò)展方法M的非泛型類型聲明C,則這些擴(kuò)展方法的集合為候選集。 · 如果在任何封閉命名空間聲明或編譯單元中都找不到候選集,則會(huì)出現(xiàn)編譯時(shí)錯(cuò)誤。 · 否則,將對(duì)候選集應(yīng)用重載決策。如果找不到一個(gè)最佳方法,則會(huì)出現(xiàn)編譯時(shí)錯(cuò)誤。 · C是將最佳方法聲明為擴(kuò)展方法的類型。 · 如果將C用作目標(biāo),則將以靜態(tài)方法調(diào)用的形式處理該方法調(diào)用。 上述規(guī)則表示,實(shí)例方法優(yōu)先于擴(kuò)展方法,內(nèi)部命名空間聲明中可用的擴(kuò)展方法優(yōu)先于外部命名空間聲明中可用的擴(kuò)展方法,并且直接在命名空間中聲明的擴(kuò)展方法優(yōu)先于通過(guò) using 命名空間指令導(dǎo)入該命名空間的擴(kuò)展方法。例如: 1 public static class E2 {3 public static void F(this object obj, int i) { }4 public static void F(this object obj, string s) { }5 }6 class A { }7 class B8 {9 public void F(int i) { }10 }11 class C12 {13 public void F(object obj) { }14 }15 class X16 {17 static void Test(A a, B b, C c) {18 a.F(1); // E.F(object, int)19 a.F("hello"); // E.F(object, string)20 b.F(1); // B.F(int)21 b.F("hello"); // E.F(object, string)22 c.F(1); // C.F(object)23 c.F("hello"); // C.F(object)24 }25 }26 ![]() 在該示例中,B 的方法優(yōu)先于第一個(gè)擴(kuò)展方法,而 C 的方法優(yōu)先于這兩個(gè)擴(kuò)展方法。 1 public static class C2 {3 public static void F(this int i) { Console.WriteLine("C.F({0})", i); }4 public static void G(this int i) { Console.WriteLine("C.G({0})", i); }5 public static void H(this int i) { Console.WriteLine("C.H({0})", i); }6 }7 namespace N18 {9 public static class D10 {11 public static void F(this int i) { Console.WriteLine("D.F({0})", i); }12 public static void G(this int i) { Console.WriteLine("D.G({0})", i); }13 }14 }15 namespace N216 {17 using N1;18 public static class E19 {20 public static void F(this int i) { Console.WriteLine("E.F({0})", i); }21 }22 class Test23 {24 static void Main(string[] args)25 {26 1.F();27 2.G();28 3.H();29 }30 }31 }32 ![]() 該示例的輸出為: E.F(1) D.G 優(yōu)先于 C.G,而 E.F 優(yōu)先于 D.F 和 C.F。 |
|
|
來(lái)自: kittywei > 《111.38-c#類》