委託和lambda表達式,Action和Func

轉自博客園(殉殤)html

委託和lambda表達式,Action和Func

一、爲何要用委託

咱們爲何要有委託?任何東西存在即合理,不合理的也會被時間淘汰掉,委託既然存在確定有存在的必要,咱們來看一下何時能夠用到委託。算法

接下來咱們有個需求,就是調用一個方法,取出1-1000個數字中全部是10的倍數的數字c#

public static List<int> GetNum() {
    List<int\> lst = new List<int>(); //這個算法是最簡陋的,可是舉這個例子是最合適的
    for (int i = 1; i < 1000; i++)
    { if (i%10==0) {
            lst.Add(i);
        }
    } return lst;
}

這個很好寫,可是若是有一天,咱們的需求變了,想取出1-1000個數字中全部是8的倍數的數字,那咱們應該怎麼寫?是否是隻要將if裏面的條件改成i%8==0就好了,可是有一點變更的話就修改方法,說明這個方法寫的並很差,若是方法很複雜的話修改也很艱難。可能有人會說在添加一個獲取是8的倍數的方法,這樣的話會增長數據冗餘,也就是重複的內容。函數

若是咱們能夠傳遞方法的話,只要傳過來一個(有一個參數爲int類型返回值爲Boolean類型的方法),這個問題將不是問題指針

public static List<int> GetNum(有一個int類型的參數返回值爲Boolean類型的方法) {
    List<int\> lst = new List<int>();
    for (int i = 1; i < 1000; i++)
    { if (有一個int類型的參數返回值爲Boolean類型的方法) {
            lst.Add(i);
        }
    } return lst;
}

是否是咱們將想要獲取什麼樣的數字這個操做來交給了調用者,不管調用者想獲取1-1000之內什麼樣的數字均可以完成。可是這個方法的前提就是能夠傳遞方法,這個時候咱們就須要用到委託了。code

二、委託如何使用

委託其實就是一個可以指向方法的 指針,定義了一個委託就是定義了一個 類型

首先咱們先來定義一個委託,也就是定義一個類型htm

//訪問修飾符  委託關鍵字  方法的返回值類型  要定義的類型名(參數1,參數2.....);
public delegate Boolean DelegateFunc(int x);

委託定義好了,也就是說咱們已經定義好了一個DelegateFunc類型,這個類型的使用方法就和public class DelegateFunc{}寫了一個類是同樣的,由於都是定義了一個類型,既然你們都是類型,那用法確定都是同樣的,咱們先來看一下聲明普通的類型是如何聲明的對象

//類型 變量名 = 實例化一個Object類型的對象(構造函數有無參數)
Object obj = new Object();

而DelegateFunc既然也是咱們定義好的一個類型,那用法天然同樣(由於構造函數須要參數,因此下面這樣寫是不對的,沒有傳入參數)blog

//類型       變量名 = 實例化一個DelegateFunc類型的對象(構造函數有無參數)
DelegateFunc func = new DelegateFunc();

委託是一個可以指向方法的指針,而它的構造函數就是須要一個方法,接着咱們來定義一個返回值爲Boolean,能接收一個int類型參數的方法繼承

//至關於方案1
public static Boolean Condition1(int i)
{ //模擬複雜的操做 至關於return i%10==0;
    int x = i % 10; if (i % 10 == 0)
    { return true;
    } else { return false;
    }
}

定義好了方法咱們再來實例化一個DelegateFunc類型的對象

//構造函數放入方法的話不須要帶(),帶()的話是調用
DelegateFunc func = new DelegateFunc(Condition1);

下面看一下下面這種聲明委託類型的方式

//一樣都是類型Object類型能夠這樣寫 //由於String最終是繼承自Object,而且String能夠默認轉換爲Object
Object obj = "obj"; //而DelegateFunc也能夠經過這種方式賦值,這說明Condition1能夠默認轉換爲委託類型
DelegateFunc func = Condition1;

實例化完成以後func變量就會指向Condition1方法,調用方式以下

//調用委託類型的對象和調用普通的方法是同樣的
func(10);

而後咱們把剛纔寫的GetNum方法修改成以下的樣子,參數爲接收一個DelegateFunc類型的參數,也就是委託類型

public static List<int> GetNum(DelegateFunc func)
{
    List<int\> lst = new List<int>();
    for (int i = 1; i < 1000; i++)
    { //調用傳過來的方法,根據調用者傳過來的方法拿到想要的數字
        if (func(i))
        {
            lst.Add(i);
        }
    } return lst;
}

在Main方法中調用GetNum方法

//聲明委託
DelegateFunc func = new DelegateFunc(Condition1); //調用方法
List<int\> lst = GetNum(func); //也能夠直接調用,由於都會默認轉換 //List<int> lst = GetNum(Condition1); //輸出
foreach (int item in lst)
{
    Console.WriteLine(item);
}

輸出

若是咱們有新的方案的話,只須要在新建一個方案,而後傳入方法中,好比咱們還看剛纔那個求1-1000之內8的倍數,咱們只須要聲明一個新的方案

//聲明一個新的方案2
public static Boolean Condition2(int i) { //一樣模擬複雜的操做 至關於return i%8==0;
    int x = i % 8; if (i % 8 == 0)
    { return true;
    } else { return false;
    }
}

而後和剛纔同樣,聲明一個委託就行,傳入GetNum就行。

不過咱們看一下,雖然已經比較簡化代碼了,可是寫起來仍是很麻煩,而後咱們來看一下lambda表達式

三、lambda表達式

首先lambda表達式只是方法的一種寫法!lambda聲明的方法是匿名方法,它和委託並非綁死的,這是兩個東西,可是lambda表達式和委託結合使用是很是常見的!

 看一下lambda表達式的語法,也就是函數的另外一種寫法

//能夠這樣寫 //DelegateFunc func = new DelegateFunc((i) => //{ // return i % 8 == 0; //}); //也能夠這樣 不進行new DelegateFunc操做,由於會默認轉換 //若是有多句的話,這樣寫每一句經過分號隔開
DelegateFunc func = (i) => { return i % 8 == 0; }; //若是隻有單句 不用寫return    默認reuturn   i%8==0 這一句計算出來的值
func = (i) => i % 8 == 0; //若是隻有一個參數   多個參數的話要(i,j,....)這樣寫
func = i => i % 8 == 0;

除此以外lambda也能夠用來聲明方法,貌似只能寫一句,,,,

//無返回值
public static void HelloWord() => Console.WriteLine("Hello Word!"); //有返回值
public static String GetHelloWord() => "Hello Word!";

有了lambd咱們再來調用GetNum,就會變得很是方便

//8的倍數
List<int\> lst = GetNum((i) => i % 8 == 0); //10的倍數
lst = GetNum(i => i % 10 == 0); //20的倍數
lst = GetNum(i => i % 20 == 0);

四、Action和Func

Action和Func是微軟已經定義好的的兩種委託類型,區別是Action是沒有返回值的,而Func是須要返回值的

Action使用方法

//無參數
Action action1 = () => Console.WriteLine("action"); //有參數的話調用Action<T>
Action<int\> action2 = (i) => Console.WriteLine(i); //多個參數就在生命的時候<T,T,T>
Action<int,string\> action3 = (i, str) => Console.WriteLine(i+"\\t"+str); //調用
action1();
action2(10);
action3(10,"s");

運行結果:

Func使用方法

//Func是沒有Func類型的,只有Func<T>類型
Func<string\> func1 = () => "func"; //若是須要參數 Func<T,T,T> //最後一個T類型爲返回值類型,前面的全都爲參數的類型!!!
Func<string, int\> func2 = (i) => int.Parse(i); //若是有多個參數     最後一個T類型爲返回值類型,前面的全都爲參數的類型!!!
Func<int, string, int\> func3 = (i, str) => int.Parse(i + str); //調用
Console.WriteLine(func1());
Console.WriteLine(func2("123"));
Console.WriteLine(func3(1,"23"));

運行結果

相關文章
相關標籤/搜索