1、為什么要用委托
我們?yōu)槭裁匆形??任何東西存在即合理,不合理的也會被時(shí)間淘汰掉,委托既然存在肯定有存在的必要,我們來看一下什么時(shí)候可以用到委托。
接下來我們有個(gè)需求,就是調(diào)用一個(gè)方法,取出1-1000個(gè)數(shù)字中所有是10的倍數(shù)的數(shù)字
public static List<int> GetNum() { List<int> lst = new List<int>(); //
這個(gè)算法是最簡陋的,但是舉這個(gè)例子是最合適的 for (int i = 1; i < 1000; i++) { if (i%10==0) {
lst.Add(i); } }return lst; }
這個(gè)很好寫,但是如果有一天,我們的需求變了,想取出1-1000個(gè)數(shù)字中所有是8的倍數(shù)的數(shù)字,那我們應(yīng)該怎么寫?是不是只要將if里面的條件改為i%8==0就行了,但是有一點(diǎn)變動的話就修改方法,說明這個(gè)方法寫的并不好,如果方法很復(fù)雜的話修改也很艱難。可能有人會說在添加一個(gè)獲取是8的倍數(shù)的方法,這樣的話會增加數(shù)據(jù)冗余,也就是重復(fù)的內(nèi)容。
如果我們可以傳遞方法的話,只要傳過來一個(gè)(有一個(gè)參數(shù)為int類型返回值為Boolean類型的方法),這個(gè)問題將不是問題
public static List<int> GetNum(有一個(gè)int類型的參數(shù)返回值為Boolean類型的方法) { List<int> lst =
new List<int>(); for (int i = 1; i < 1000; i++) { if
(有一個(gè)int類型的參數(shù)返回值為Boolean類型的方法) { lst.Add(i); } }return lst; }
是不是我們將想要獲取什么樣的數(shù)字
這個(gè)操作來交給了調(diào)用者,無論調(diào)用者想獲取1-1000以內(nèi)什么樣的數(shù)字都可以完成。但是這個(gè)方法的前提就是可以傳遞方法,這個(gè)時(shí)候我們就需要用到委托了。
2、委托如何使用
委托其實(shí)就是一個(gè)能夠指向方法的 指針,定義了一個(gè)委托就是定義了一個(gè) 類型
首先我們先來定義一個(gè)委托,也就是定義一個(gè)類型
//訪問修飾符 委托關(guān)鍵字 方法的返回值類型 要定義的類型名(參數(shù)1,參數(shù)2.....); public delegate Boolean
DelegateFunc(int x);
委托定義好了,也就是說我們已經(jīng)定義好了一個(gè)DelegateFunc類型,這個(gè)類型的使用方法就和public class DelegateFunc{}
寫了一個(gè)類是一樣的,因?yàn)槎际嵌x了一個(gè)類型,既然大家都是類型,那用法肯定都是一樣的,我們先來看一下聲明普通的類型是如何聲明的
//類型 變量名 = 實(shí)例化一個(gè)Object類型的對象(構(gòu)造函數(shù)有無參數(shù)) Object obj = new Object();
而DelegateFunc既然也是我們定義好的一個(gè)類型,那用法自然一樣(因?yàn)闃?gòu)造函數(shù)需要參數(shù),所以下面這樣寫是不對的,沒有傳入?yún)?shù))
//類型 變量名 = 實(shí)例化一個(gè)DelegateFunc類型的對象(構(gòu)造函數(shù)有無參數(shù)) DelegateFunc func = new
DelegateFunc();
委托是一個(gè)能夠指向方法的指針,而它的構(gòu)造函數(shù)就是需要一個(gè)方法,接著我們來定義一個(gè)返回值為Boolean,能接收一個(gè)int類型參數(shù)的方法
//相當(dāng)于方案1 public static Boolean Condition1(int i) { //模擬復(fù)雜的操作 相當(dāng)于return i%10==0;
int x = i % 10; if (i % 10 == 0) { return true; } else { return false; } }
定義好了方法我們再來實(shí)例化一個(gè)DelegateFunc類型的對象
//構(gòu)造函數(shù)放入方法的話不需要帶(),帶()的話是調(diào)用 DelegateFunc func = new DelegateFunc(Condition1);
下面看一下下面這種聲明委托類型的方式
//同樣都是類型Object類型可以這樣寫 //因?yàn)镾tring最終是繼承自O(shè)bject,并且String可以默認(rèn)轉(zhuǎn)換為Object Object obj =
"obj"; //而DelegateFunc也可以通過這種方式賦值,這說明Condition1可以默認(rèn)轉(zhuǎn)換為委托類型 DelegateFunc func =
Condition1;
實(shí)例化完成之后func變量就會指向Condition1方法,調(diào)用方式如下
//調(diào)用委托類型的對象和調(diào)用普通的方法是一樣的 func(10);
然后我們把剛才寫的GetNum方法修改為如下的樣子,參數(shù)為接收一個(gè)DelegateFunc類型的參數(shù),也就是委托類型
public static List<int> GetNum(DelegateFunc func) { List<int> lst = new List<
int>(); for (int i = 1; i < 1000; i++) { //調(diào)用傳過來的方法,根據(jù)調(diào)用者傳過來的方法拿到想要的數(shù)字 if
(func(i)) { lst.Add(i); } }return lst; }
在Main方法中調(diào)用GetNum方法
//聲明委托 DelegateFunc func = new DelegateFunc(Condition1); //調(diào)用方法 List<int> lst =
GetNum(func);//也可以直接調(diào)用,因?yàn)槎紩J(rèn)轉(zhuǎn)換 //List<int> lst = GetNum(Condition1); //輸出
foreach (int item in lst) { Console.WriteLine(item); }
?
輸出
如果我們有新的方案的話,只需要在新建一個(gè)方案,然后傳入方法中,比如我們還看剛才那個(gè)求1-1000以內(nèi)8的倍數(shù),我們只需要聲明一個(gè)新的方案
//聲明一個(gè)新的方案2 public static Boolean Condition2(int i) { //同樣模擬復(fù)雜的操作 相當(dāng)于return
i%8==0; int x = i % 8; if (i % 8 == 0) { return true; } else { return false; } }
然后和剛才一樣,聲明一個(gè)委托就行,傳入GetNum就行。
不過我們看一下,雖然已經(jīng)比較簡化代碼了,但是寫起來還是很麻煩,然后我們來看一下lambda表達(dá)式
3、lambda表達(dá)式
首先lambda表達(dá)式只是方法的一種寫法!lambda聲明的方法是匿名方法,它和委托并不是綁死的,這是兩個(gè)東西,但是lambda表達(dá)式和委托結(jié)合使用是非常常見的!
?看一下lambda表達(dá)式的語法,也就是函數(shù)的另一種寫法
//可以這樣寫 //DelegateFunc func = new DelegateFunc((i) => //{ // return i % 8 == 0;
//}); //也可以這樣 不進(jìn)行new DelegateFunc操作,因?yàn)闀J(rèn)轉(zhuǎn)換 //如果有多句的話,這樣寫每一句通過分號隔開 DelegateFunc
func = (i) => {return i % 8 == 0; }; //如果只有單句 不用寫return 默認(rèn)reuturn i%8==0
這一句計(jì)算出來的值 func = (i) => i % 8 == 0; //如果只有一個(gè)參數(shù) 多個(gè)參數(shù)的話要(i,j,....)這樣寫 func = i =>
i %8 == 0;
除此之外lambda也可以用來聲明方法,貌似只能寫一句,,,,
//無返回值 public static void HelloWord() => Console.WriteLine("Hello Word!"); //
有返回值 public static String GetHelloWord() => "Hello Word!";
有了lambd我們再來調(diào)用GetNum,就會變得非常方便
//8的倍數(shù) List<int> lst = GetNum((i) => i % 8 == 0); //10的倍數(shù) lst = GetNum(i => i %
10 == 0); //20的倍數(shù) lst = GetNum(i => i % 20 == 0);
4、Action和Func
Action和Func是微軟已經(jīng)定義好的的兩種委托類型,區(qū)別是Action是沒有返回值的,而Func是需要返回值的
Action使用方法
//無參數(shù) Action action1 = () => Console.WriteLine("action"); //有參數(shù)的話調(diào)用Action<T>
Action<int> action2 = (i) => Console.WriteLine(i); //多個(gè)參數(shù)就在生命的時(shí)候<T,T,T> Action<
int,string> action3 = (i, str) => Console.WriteLine(i+"\t"+str); //調(diào)用
action1(); action2(10); action3(10,"s");
運(yùn)行結(jié)果:
Func使用方法
//Func是沒有Func類型的,只有Func<T>類型 Func<string> func1 = () => "func"; //如果需要參數(shù)
Func<T,T,T>//最后一個(gè)T類型為返回值類型,前面的全都為參數(shù)的類型!!! Func<string, int> func2 = (i) => int
.Parse(i);//如果有多個(gè)參數(shù) 最后一個(gè)T類型為返回值類型,前面的全都為參數(shù)的類型!!! Func<int, string, int> func3 =
(i, str) =>int.Parse(i + str); //調(diào)用 Console.WriteLine(func1());
Console.WriteLine(func2("123")); Console.WriteLine(func3(1,"23"));
運(yùn)行結(jié)果
?
熱門工具 換一換