筆記來自於《.NET4.0物件導向編程漫談 基礎篇》
Tag:多路委託,泛型委派,Func系列委託、Action系列委託與MethodInvoker、Predicate<T>委託
委託調用列表
委託變數可以組合多個方法並批量執行它們
組合方法:使用加法、減法運算子
Delegate類定義了一個GetInvocationList靜態方法用於擷取委託調用列表,通過這個函數可以瞭解委託的方法集
一個多路委託變數可以引用多個方法,執行一個多路委託變數,會導致它所包含的所有方法被順序執行。
委託變數的內容是“唯讀”的,合并或分割委託列表得到的只是一個新的委託調用列表。
泛型委派:
.NET2.0開始,委託開始支援泛型技術,即泛型委派
一個簡單的泛型委派例子:
public delegate T MyGenericDelegate<T>(T obj1,T obj2);
static int MyFunc(int val1,int val2)
{
return val1*val2;
}
void MainFormLoad(object sender,EventArgs e)
{
MyGenericDelegate<int> del;
del=MyFunc;
label1.Text=del(12,22).ToString();
}
可以看到,泛型委派的使用與普通委託類似,不同之處在於使用泛型委派時需要指定泛型參數。
Func系列委託:
Func系列委託的定義:
public delegate TResult Func<TResult>();
public delegate TResult Func<T,TResult>(T arg);
public delegate TResult Func<T1,T2,TResult>(T1 arg1,T2 arg2);
public delegate TResult Func<T1,T2,T3,TResult>(T1 arg1,T2 arg2,T3 arg3);
public delegate TResult Func<T1,T2,T3,T4,TResult>(T1 arg1,T2 arg2,T3 arg3,T4 arg4);
Func委託聲明的最後一個泛型型別參數是委託所接收方法的傳回值類型,前面的泛型參數就是委託所接收方法的形參類型
Func系列委託的例子:
public delegate TResult Func<TResult>();
public delegate TResult Func<T,TResult>(T arg);
public delegate TResult Func<T1,T2,TResult>(T1 arg1,T2 arg2);
public delegate TResult Func<T1,T2,T3,TResult>(T1 arg1,T2 arg2,T3 arg3);
public delegate TResult Func<T1,T2,T3,T4,TResult>(T1 arg1,T2 arg2,T3 arg3,T4 arg4);
static int Add(int i,int j){return i+j;}
static int Multiply(int i,int j){return i*j;}
static int Process(Func<int,int,int> op,int[] numbers,int from,int to)
{
int result=numbers[from];
for(int i=from;i<=to;i++)
result=op(result,numbers[i]);
return result;
}
void MainFormLoad(object sender,EventArgs e)
{
int[] numbers=new int[7]{0,2,4,1,6,8,10};
label1.Text=Process(Add,numbers,0,3).ToString()+"\n";
label1.Text+=Process(Multiply,numbers,3,6).ToString();
}
定義了多個兩個方法Add和Multiply,和一個數組處理方法Process,它以委託方法作為參數處理數組
Action系列委託與MethodInvoker
Func泛型委派所能接收的方法都有傳回值,Action系列委託是接收返回void的系統預定義委託
public delegate void Action();
public delegate void Action<T>(T obj);
public delegate void Action<T1,T2>(T1 arg1,T2 arg2);
public delegate void Action<T1,T2,T3>(T1 arg1,T2 arg2,T3 arg3);
使用方法和Func一樣
MethodInvoker委託位於System.Windows.Forms中,聲明如下:
public delegate void MethodInvoker();
和無型別參數的Action委託等價,用法也一樣
Predicate<T>委託:
Predicate<T>委託在.NET基底類別庫中經常出現,定義如下:
public delegate bool Predicate<T>(T obj);
此委託引用一個返回bool值的方法,在實際開發中,經常使用Prodicate<T>委託變數引用一個“判斷條件函數”,在判斷條件函數內部書寫代碼錶明函數參數所引用的對象滿足的條件,條件滿足時,函數返回true,一個例子:
class MyClass
{
public int Value;
public string Info;
}
private static List<MyClass> GetMyClassList()
{
List<MyClass> lst = new List<MyClass>();
Random ran = new Random();
MyClass obj = null;
for (int i = 0; i < 10; i++)
{
obj = new MyClass();
obj.Value=ran.Next(1,100);
obj.Info="object "+i.ToString();
lst.Add(obj);
}
return lst;
}
static bool GreaterThan50(MyClass elem)
{
if (elem.Value > 50)
return true;
return false;
}
void MainFormLoad(object sender,EventArgs e)
{
Predicate<MyClass> pred = GreaterThan50;
List<MyClass> lst = GetMyClassList();
MyClass foundElement= lst.Find(pred);
if (foundElement != null)
label1.Text=string.Format("找到了合格對象。Infomation={0},Value={1}", foundElement.Info, foundElement.Value);
else
label1.Text="未找到合格對象";
}
產生一個List<MyClass>,並且尋找其中MyClass對象的Value值大於50的輸出資訊
泛型集合List<T>中定義了一個Find方法:
public T Find(Predicate<T> match);
Lis<T>.Find方法遍曆集合中的所有對象,並將每個對象作為Predicate<T>所引用的“判斷條件函數”實參調用此函數。
使用Predicate<T>委託時,其判斷條件一般是“外部硬性規定的”而非由資料自身指定,否則就不適合採用此類委託。
下節還有匿名方法與Lambda運算式、回調