前言
在上篇文章C#中委託(delegate)和多播委託的理解中已經基本瞭解了委託的用法。
由於委託封裝的方法我們不一定知道其傳入的參數和返回值,例如之前說的的排序方法—————在對象的排序算法中,需要對對象進行比較,而不同對象比較的方法不同,所以比較兩個對象的方法的引用可以作爲參數傳遞到排序算法中,這個時候就需要傳遞方法。
當我們要生成一個封裝比較對象的方法的委託時,我們並不知道該方法傳入對象是什麼,所有我們必須引入泛型的概念來輔助委託的使用。
Action<T>
和Func<T>
泛型委託
除了爲每個參數和返回類型定義一個新委託類型外(基本的委託定義方法),還有就是使用Action<T>
和Func<T>
定義委託,Action<T>
委託表示引用一個void
返回類型的方法,且最多可以傳遞16種參數;Func<T>
類似,但允許調用帶返回值的方法。
注意對比普通委託和泛型委託的定義和使用的區別。
泛型委託的定義和使用:
對於上篇加減的例子,可以直接將Func<int, int,int>
類型的委託作爲參數:
public int numMethod(int num1, int num2, Func<int, int,int> callback)
{
return callback(num1,num2);
}
這兩種方法的區別就在於,我們可以跳過普通委託聲明委託對象的過程,其實我們通過查看元數據就可以看出,其時是框架給我們封裝好了Func<int, int,int>
方法,其實普通委託和泛型委託並無太大區別:
public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2);
在我們調用Func<int, int,int>
方法是其實還是生成了一個委託對象,該委託封裝的方法的參數和返回值的類型會自動設置爲我們實例該委託的方法的參數和返回值,所以我們使用了T來代表任意類型的參數和返回值;
總結
Action<T>
和Func<T>
泛型委託和普通委託,沒有本質區別,普通委託是手動設置委託對象的參數和返回值,而泛型委託會根據我們傳入的方法的參數和返回值自動設置其對應的委託對象;
由於Action<T>
和Func<T>
相當於聲明好的委託,我們調用它,只是給它實例化,所以不能和聲明普通委託一樣在類的外部調用!
更加具體的理解就是:
如果普通委託可以封裝的具有相同類型參數和返回值的方法,而泛型委託可以封裝的就是參數和方法值的類型具有相同對應關係的方法。
那麼這樣帶來的好處有什麼?
匿名方法
和
Lambda表達式
的使用
可以通過下面這個實例體現出來
重點
這個實例裏泛型委託,匿名方法,Lambda表達式,泛型都有出現,是一個非常好的實例!還出現了另一種泛型委託———Comparison<in T>
class Program
{
static void Main(string[] args)
{
List<StudentScore> lst = new List<StudentScore>()//需要被排序的對象組
{
new StudentScore("A",50),
new StudentScore("B",60),
new StudentScore("C",70),
new StudentScore("D",80),
new StudentScore("E",93),
new StudentScore("F",69),
new StudentScore("G",36),
new StudentScore("H",76),
new StudentScore("I",66),
new StudentScore("J",98)
};
//方法一:通過比較兩個對象的匿名函數採用Lambda表達式,來聲明該委託
Func<StudentScore, StudentScore, bool> fun = (x, y) => x.score < y.score;
//方法二:通過比較兩個對象方法,聲明該泛型委託
//Func<StudentScore, StudentScore, bool> fun = compare;
HighestScores(lst, fun);
//方法三:直接將比較對象的方法傳入
//HighestScores(lst, compare);
Console.ReadLine();
}
static public void HighestScores<T>(IList<T> sourceArray, Func<T, T, bool> comp)
{
int cnt = Convert.ToInt32((float)sourceArray.Count * 0.2);//前百分之二十
List<T> lst = sourceArray.ToList();
lst.Sort((x, y) => comp(x, y) == true ? 1 : -1);//Sort的一個重載參數爲Comparison<T>泛型委託
///Sort的參數爲一個類似於Func<>的表達式,這裏給它賦的爲一個Lambda表達式,
///當然這裏也同上面的方法二一樣可以將匿名方法抽取出來
///相當於Comparison<T> comparison=(x, y) => comp(x, y) == true ? 1 : -1;
///其中:
///public void Sort(Comparison<T> comparison);
///public delegate int Comparison<in T>(T x, T y);
///其中Comparison<in T>和前面的Func<>功能類似
foreach (T t in lst.Take(cnt))//返回排序好對象組的前cnt個對象
Console.WriteLine(t);
}
static public bool compare(StudentScore x ,StudentScore y)
{
return x.score < y.score?true : false;
}
}
class StudentScore
{
public StudentScore(string n, int s)
{
this.name = n;
this.score = s;
}
public string name;
public int score;
public override string ToString()
{
return string.Format("{0} {1}", this.name, this.score);
}
}
事件(event)和委託(delegate)的綜合運用實例(WinForm控件事件執行流程和原理),和EventHandler委託