C#匿名方法美澳、Lambda表達式和各種泛型委托

Linq查詢與高級C#編程機器理論研究基礎

C#委托解決的是對象之間的逆向傳遞問題僚害,其次缴饭,委托還有其他的用途(匿名方法暑劝、Lambda表達式、和泛型結合)颗搂,涉及到高級編程中(LInq查詢担猛、擴展方法)的底層原理。

一丢氢、匿名方法傅联、Lambda表達式

1、匿名方法

概念:一個只有關鍵字delegate疚察、方法參數蒸走、方法體,但沒有具體的名稱貌嫡,這種方法稱為匿名方法

好處:將具體方法和委托直接關聯到一起比驻,如果我們基于委托只需要一個方法的時候,匿名方法顯得更加簡單



CalculatorDelegate cal2 = delegate (int a, int b)

? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? return a - b;

? ? ? ? ? ? ? };



2岛抄、Lambda表達式

C#3.0以后别惦,可以使用Lambda表達式更加簡練地編寫程序塊。

//將匿名方法使用Lambda表達式簡化編寫


? ? ? ? ? ? CalculatorDelegate cal3 = (int a, int b) => { return a + b};




//進一步簡化:假如方法中只有一行代碼


? ? ? ? ? ? CalculatorDelegate cal4 = (a, b) => a - b;


【1】在Lambda表達式中夫椭,參數類型可以是明確類型掸掸,也可以是推斷類型

【2】如果是推斷類型,則參數類型可以由編譯根據上下文自動推斷出來

【3】運算符=>讀作goes to,運算符左邊輸入參數(如果有)扰付,右邊是表達式或語句塊

【4】表達式兩種方式:

(input args)=>表達式

(input args)=>{語句1堤撵;語句2;語句3……}

【5】Lambda表達式與匿名方法的比較

(1)Lambda表達式本身就是匿名方法

(2)Lambda表達式允許不指明參數類型悯周、但是匿名方法必須明確

(3)Lambda表達式允許單一的表達式或多條語句組成粒督,而匿名方法不允許單一表達式

例:


public void test()

? ? ? ? {

? ? ? ? ? ? //【1】委托關聯獨立的方法

? ? ? ? ? ? CalculatorDelegate cal1 = Add;

? ? ? ? ? ? //【2】委托關聯匿名方法

? ? ? ? ? ? CalculatorDelegate cal2 = delegate (int a, int b)

? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? return a - b;

? ? ? ? ? ? ? };

? ? ? ? ? ? //【3】將匿名方法使用Lambda表達式簡化編寫

? ? ? ? ? ? CalculatorDelegate cal3 = (int a, int b) => { return a + b};

? ? ? ? ? ? //進一步簡化:假如方法中只有一行代碼

? ? ? ? ? ? CalculatorDelegate cal4 = (a, b) => a - b;

? ? ? ? ? ? sayHelloDelegate sayHello = () => "歡迎你";

? ? ? ? ? ? Console.WriteLine("通過匿名方法計算:20-30="+cal2(20,30));

? ? ? ? }-

? ? ? ? private int Add(int a, int b)

? ? ? ? {

? ? ? ? ? ? return a + b;

? ? ? ? } //根據委托的使用可以繼續(xù)添加其他方法

? ? ? ? public delegate int CalculatorDelegate(int a, int b);

? ? ? ? public delegate string sayHelloDelegate();

? ? }


二、自定義泛型委托

1禽翼、為什么要使用泛型委托屠橄?

普通委托在數據類型上的限制是非常嚴格的,無法適應需求變化

2闰挡、泛型委托定義:本質上和泛型方法非常類似锐墙,泛型委托關聯的時候,可以是具體方法长酗、匿名方法溪北、Lambda表達式



/// <summary>

? ? /// 泛型委托

? ? /// </summary>

? ? class GenericDelegate

? ? {

? ? ? ? public void Test()

? ? ? ? {

? ? ? ? ? ? //使用泛型委托:具體方法

? ? ? ? ? ? MyGenericDelegate<int> myDelegate1 = Add;

? ? ? ? }

? ? ? ? //根據委托定義方法

? ? ? ? static int Add(int a ,int b)

? ? ? ? {

? ? ? ? ? ? return a + b;

? ? ? ? }

? ? ? ? static double Sub(double a,double b)

? ? ? ? {

? ? ? ? ? ? return a - b;

? ? ? ? }

? ? ? ? public delegate int MyGenericDelegate<T>(T parameter1, T parameter2);


3、問題引出:如果使用多個參數夺脾,按照上述方法不得不定義很多這種泛型委托之拨,非常麻煩

三、系統(tǒng)泛型委托

為了方便開發(fā)者咧叭,.NET基類庫中針對常用的情況蚀乔,提供了預定委托。這些委托使用非常廣泛

兩種方式:一種是有返回值Func<args>菲茬,一種是沒有返回值Action<args>

Action<args>在多線程中用的非常多

Func<args>在linq中用的非常多


Func<args>



/// <summary>

? ? /// 有返回值的系統(tǒng)類型的泛型委托

? ? /// 目的:為了方便開發(fā)者吉挣,.NET基類庫中針對常用的情況,提供了預定委托婉弹。這些委托使用非常廣泛

? ? /// </summary>

? ? class FunDelegateDemo

? ? {

? ? ? ? #region Func委托的基本使用

? ? ? ? public void Test()

? ? ? ? {

? ? ? ? ? ? //【1】Func關聯具體方法

? ? ? ? ? Func<int, int, double> myfunc1= Add1;

? ? ? ? ? ? //【2】Func直接使用Lambda表達式

? ? ? ? ? ? Func<int, int, double> myFunc = (a, b) => a + b;

? ? ? ? }

? ? ? ? private double Add1(int a, int b)

? ? ? ? {

? ? ? ? ? ? return a + b;

? ? ? ? }

? ? ? ? #endregion




? ? ? ? #region Func委托的重要使用

? ? ? ? //問題:給定一個數組睬魂,從數組中指定位置抽取3個數,求和镀赌,求積

? ? ? ? //思考:運算的要求不一樣(求和氯哮,求積),兩種運算可以單獨作為方法

? ? ? ? ? ? #region 普通方法

? ? ? ? ? ? public int Sum(int[] nums, int from, int to)

? ? ? ? {

? ? ? ? ? ? int result = 0;

? ? ? ? ? ? for (int i = from; i <= to; i++)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? result += nums[i];

? ? ? ? ? ? }

? ? ? ? ? ? return result;

? ? ? ? }

? ? ? ? ? ? public int Mul(int[] nums, int from, int to)

? ? ? ? {

? ? ? ? ? ? int result = 1;

? ? ? ? ? ? for (int i = from; i <= to; i++)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? result *= nums[i];

? ? ? ? ? ? }

? ? ? ? ? ? return result;

? ? ? ? }//還可以繼續(xù)加新的方法

? ? ? ? ? ? public void Test2()

? ? ? ? {

? ? ? ? ? ? int[] nums = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };

? ? ? ? ? ? int result1 = Sum(nums, 0, 2);

? ? ? ? ? ? Console.WriteLine("10,9,8求和為:" + result1);

? ? ? ? ? ? int result2 = Mul(nums, 0, 2);

? ? ? ? ? ? Console.WriteLine("10,9,8求積為:" + result1);

? ? ? ? }

? ? ? ? ? ? #endregion




? ? ? ? ? ? #region 使用Func委托商佛,將“運算”本身作為方法參數

? ? ? ? ? ? public int Operation(Func<int,int,int> method ,int[] nums,int from,int to? )

? ? ? ? ? ? {

? ? ? ? ? ? int result = nums[from];//把第一個值作為基數

? ? ? ? ? ? for (int i = from+1; i <= to; i++)

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? result =method(result,nums[i]);

? ? ? ? ? ? ? ? }

? ? ? ? ? ? return result;

? ? ? ? ? ? }

? ? ? ? public void Test3()

? ? ? ? {

? ? ? ? ? ? int[] nums = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };

? ? ? ? ? ? //將Func作為方法參數喉钢,結合Lambda表達式

? ? ? ? ? ? int result1 = Operation((a,b)=>a+b, nums,0, 2);

? ? ? ? ? ? Console.WriteLine("10,9,8求和為:" + result1);

? ? ? ? ? ? int result2 = Operation((a, b) => a * b, nums, 0, 2);

? ? ? ? ? ? Console.WriteLine("10,9,8求積為:" + result2);

? ? ? ? }

? ? ? ? #endregion

? ? ? ? #endregion

? ? }

}




Func<args>



/// <summary>

? ? /// Action系統(tǒng)泛型委托

? ? /// 和Func相比,Action委托沒有參數威彰,所以Action委托接收的是一個沒有返回值的方法

? ? /// </summary>

? ? class ActionDenlegateDemo

? ? {

? ? ? ? public void Test()

? ? ? ? {

? ? ? ? ? ? Action<string> action = (name) => Console.WriteLine($"歡迎參加【 { name}】的活動");

? ? ? ? ? ? action("發(fā)呆");

? ? ? ? }

? ? }


Action委托與Func系列類似出牧,有若干個重載方法,可以接收0-4個參數歇盼,且返回值為void類型的方法


結論:泛型委托作為方法參數舔痕,實際上傳遞的是一個具體的方法或者一個Lambda表達式(多態(tài)的一種表現)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子伯复,更是在濱河造成了極大的恐慌慨代,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件啸如,死亡現場離奇詭異侍匙,居然都是意外死亡,警方通過查閱死者的電腦和手機叮雳,發(fā)現死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進店門想暗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人帘不,你說我怎么就攤上這事说莫。” “怎么了寞焙?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵储狭,是天一觀的道長。 經常有香客問我捣郊,道長辽狈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任呛牲,我火速辦了婚禮刮萌,結果婚禮上,老公的妹妹穿的比我還像新娘侈净。我一直安慰自己尊勿,他們只是感情好僧凤,可當我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布畜侦。 她就那樣靜靜地躺著,像睡著了一般躯保。 火紅的嫁衣襯著肌膚如雪旋膳。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天途事,我揣著相機與錄音验懊,去河邊找鬼。 笑死尸变,一個胖子當著我的面吹牛义图,可吹牛的內容都是我干的。 我是一名探鬼主播召烂,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼碱工,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起怕篷,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤历筝,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后廊谓,有當地人在樹林里發(fā)現了一具尸體梳猪,經...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年蒸痹,在試婚紗的時候發(fā)現自己被綠了春弥。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡叠荠,死狀恐怖惕稻,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情蝙叛,我是刑警寧澤俺祠,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站借帘,受9級特大地震影響蜘渣,放射性物質發(fā)生泄漏。R本人自食惡果不足惜肺然,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一蔫缸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧际起,春花似錦拾碌、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至灾前,卻和暖如春防症,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背哎甲。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工蔫敲, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人炭玫。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓奈嘿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親吞加。 傳聞我的和親對象是個殘疾皇子裙犹,可洞房花燭夜當晚...
    茶點故事閱讀 44,955評論 2 355