C#中匿名函數、委托delegate和Action、Func、Expression、還有Lambda的關系和區別


以前一直迷迷糊糊的,現在總算搞明白。

Lambda表達式

Lamda表達式基本寫法是()=>{ };
Lambda和方法一樣都可以傳入參數和擁有返回值。(int x)=>{return x;};
Lambda表達式並不是C#獨有的,其它語言也擁有Lambda表達式。

一些文檔上寫Lambda是匿名函數,我認為是不對的,Lambda可以表示一個匿名函數,但是還可以來表示Linq表達式啊。

delegate委托

委托基本的使用包括聲明一個委托、實例化一個委托、使用一個委托

// 聲明一個委托,類型是myDelegate,
public delegate void myDelegate(string str); 
public static void HellowChinese(string strChinese) 
{ 
    Console.WriteLine("Good morning," + strChinese); 
    Console.ReadLine(); 
} 
// 實例化   
myDelegate d = new myDelegate(HellowChinese); 
// 使用
d("Mr wang");

委托很好用。當編程到一定階段,發現只傳遞一個或幾個int、strig類型參數是不夠的,希望可以把一段代碼進行傳遞來執行某個操作,委托提供了這樣的途徑,委托提供了一種可以直接訪問類中方法的途徑,可以將方法當作一個參數傳遞從而使用

匿名函數

上面已經講到匿名函數了。函數和方法等價,用來封裝一段代碼片以便隨時使用,有的有返回值有的無返回值。寫在類里面。

但是如果我只想把這段代碼片使用一次呢?再聲明一個類、一個方法實在太麻煩,這時候匿名函數就擁有了價值。用來封裝一段代碼、直接執行或者傳遞。

匿名函數總是和委托一齊使用,因為匿名函數方便了委托的使用(不用聲明一個類了)

匿名方法兩種實現方式:

使用Lambda表達式:

        public delegate void Seep();
        static void Main(string[] args)
        {

            Seep s = () => { Console.WriteLine(2); Console.WriteLine(1); };
        }

使用委托

 

        public delegate void Seep();
        static void Main(string[] args)
        {
            Seep see = delegate () { Console.WriteLine(1); };
        }

 

Action、Func、Predicate

委托需要先聲明一個類型才能使用,這很麻煩,比如我在某一個命名空間聲明了一個沒有返回值的委托myDelegate,然后想要這個委托的時候,每個命名空間都要引用這個命名空間,這太不友好了。

微軟直接就在框架中定義了三種委托:Action、Func、Predicate。這三種委托是C#的System命名空間中已經定義好的,如Action

上面已經通過匿名函數實現了不用聲明類,現在通過C#預定義的委托類型實現了不用聲明委托類型,那么現在就可以直接寫代碼片來執行了

這三種委托的相應泛型形式,可以寫出如下代碼:

            #region 無參數無返回值
            // lambda實現委托實例
            Action a1 = () => Console.WriteLine(1);
            a1();
            // delegate實現委托實例,下面不再演示delegate。
            Action a2 = delegate { Console.WriteLine(1); };
            a2();
            #endregion

            #region 有參數無返回值
            Action<int> a3 = (x) => Console.WriteLine(x);
            a3(1);
            #endregion

            #region 無參數有返回值的情況
            Func<int> e1= ()=> 1;
            var value1= e1();
            #endregion

            #region 有參數有返回值的情況
            // 最后一個泛型是返回值的類型
            Func<int,int> e2 = (x) => x+1;
            int value2= e2(1);
            // 多參數情況
            Func<int, int,int> e3 = (x,x2) => x+x2 + 1;
            int value3 = e3(1,2);
            #endregion

            #region 返回值是布爾類型
            // 其實Predicate可以用Func返回值是bool來代替的。
            Predicate<int> p = (x) => x > 0;
            bool value4 = p(1);
            #endregion

委托還有一些特性(如可加性),感興趣的可以查閱相關資料。

Expression

Expression指的是System.Linq.Expressions,是Linq表達式,表達式樹,不是Lambda表達式!!

Linq表達式用於離線集合的查詢。什么是離線集合?最常用的是EF里面的DBContext,我也只用過這個,所以我不想那么多,就把Expression當成EF里面使用的就行了。

1、只能接受Lambda表達式表示的委托

2、Lambda表達式只能有一條語句。

            Expression<Func<int,int>> eeee = (x)=> x+ 1 ;

總結

1、都是希望可以單獨引用一段代碼片引起的。
2、然后引用了委托delegate,delegate的使用方式為聲明類型-實例化類型(傳入想要使用的類的方法)-使用委托(使用方法)
3、簡化操作,使用(通過Lambda或者delegate)匿名方法來直接聲明一段代碼片,避免聲明所想使用的類的方法
4、簡化操作,直接使用C#預定義的三種委托Action、Func、Predicate,連聲明委托都省了。
5、本文代碼:https://github.com/Beiluola/delegateDemo

注意

1、匿名函數總是和委托一起使用(三種預定義委托)
2、使用三種預定義委托就可以滿足大多數需求。
3、Expression是Linq表達式樹,只能使用接受一句lambda表達式。和匿名函數無關。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM