定義
用來擴充已定義類型中的方法成員
在擴充方法之前,擴充一個方法需要使用繼承來擴充現有類來擴充現有類型,并且值類型和密封類型(sealed)是不能被繼承的定義規則
擴充方法的定義規則
- 擴充方法必須在一個非嵌套、非泛型的靜态類(即在類中定義類)中進行定義
- 至少有一個參數
- 第一個參數必須加上this關鍵字作為字首(第一個參數類型也被稱為擴充類型,即指方法對這個類型進行擴充)
- 第一個參數不能使用任何其他的修飾符(如ref out等)
- 第一個參數的類型不能是指針類型
代碼示例:
using system;
using system.Collection.Generic;
//擴充方法必須定義在非泛型靜态類中
public static class ListExten
{
//定義擴充方法
public static int JSum(this IEnumerable source)
if(source==null)
{
throw new ArgumentNukkException("輸入數組為空");
}
int jsum=0;
bool flag=false;
foreach(int current in source)
{
if(!flag)
{
jsum+=current;
flag=true;
}
else
{
flag=false;
}
}
return jsum;
}
使用
代碼示例:
using system;
using system.Collection.Generic;
class program
{
//調用擴充方法
static void Main(string[] args)
{
Listsource=new List{1,2,3,4,5,6};
//第一種調用方式
int jsum=ListExten.JSum(source);
//第二種調用方式
int jsum1=source.JSum();
Console.WriteLine("數組之和為:"+jsum);
Console.WriteLine("數組之和為:"+jsum1);
Console.Readline;
}
}
編譯器發現擴充方法
當編譯器看到類型的變量在調用方法時,會首先在對象的執行個體方法中查找,如果沒有找到就查找是否存在合适的擴充方法,此時編譯器會檢查所有導入的命名空間和目前命名空間中的擴充方法,并将變量類型比對到擴充類型,這裡存在一個隐式轉換的擴充方法(子類到父類的轉換可以通過隐式轉換來完成) 擴充方法在智能提示中都有一個向下的箭頭來進行辨別,編譯器則通過System.Runtime.CompilerServices.ExtensionAttribute屬性來識别擴充方法
當編譯器看到某個類型的變量在調用方法時 查找順序:
- 對象的執行個體方法
- 目前命名空間下的擴充方法
- 導入命名空間下的擴充方法
注意事項
- 如果擴充的類型中定義了無參數的執行個體方法名(如:Print),則在擴充方法在定義該名稱的擴充方法(Print),則執行個體在後續調用時隻能提示不會出現該擴充方法
- 如果在同一個命名空間下的兩個類中含有擴充類型相同的方法,編譯器就不知道該調用哪個方法了就會出現編譯錯誤
空引用也可以調用擴充方法
空引用null上調用執行個體方法會引發NullReferenceException異常,但是在空引用上卻可以調用擴充方法
public static class NullExte
{
//第一種擴充 此種擴充方法會對其他子類産生污染
public static bool IsNull(this object obj)
{
return obj==null;
}
//第二種擴充方法
public static bool isNull(this string str)
{
return str==null;
}
}