C#匿名方法、Lambda表達(dá)式和各種泛型委托

Linq查詢與高級C#編程機(jī)器理論研究基礎(chǔ)

C#委托解決的是對象之間的逆向傳遞問題,其次,委托還有其他的用途(匿名方法、Lambda表達(dá)式、和泛型結(jié)合),涉及到高級編程中(LInq查詢、擴(kuò)展方法)的底層原理。

一、匿名方法、Lambda表達(dá)式

1、匿名方法

概念:一個(gè)只有關(guān)鍵字delegate、方法參數(shù)、方法體,但沒有具體的名稱,這種方法稱為匿名方法

好處:將具體方法和委托直接關(guān)聯(lián)到一起,如果我們基于委托只需要一個(gè)方法的時(shí)候,匿名方法顯得更加簡單



CalculatorDelegate cal2 = delegate (int a, int b)

? ? ? ? ? ? ? {

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

? ? ? ? ? ? ? };



2、Lambda表達(dá)式

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

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


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




//進(jìn)一步簡化:假如方法中只有一行代碼


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


【1】在Lambda表達(dá)式中,參數(shù)類型可以是明確類型,也可以是推斷類型

【2】如果是推斷類型,則參數(shù)類型可以由編譯根據(jù)上下文自動(dòng)推斷出來

【3】運(yùn)算符=>讀作goes to,運(yùn)算符左邊輸入?yún)?shù)(如果有),右邊是表達(dá)式或語句塊

【4】表達(dá)式兩種方式:

(input args)=>表達(dá)式

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

【5】Lambda表達(dá)式與匿名方法的比較

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

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

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

例:


public void test()

? ? ? ? {

? ? ? ? ? ? //【1】委托關(guān)聯(lián)獨(dú)立的方法

? ? ? ? ? ? CalculatorDelegate cal1 = Add;

? ? ? ? ? ? //【2】委托關(guān)聯(lián)匿名方法

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

? ? ? ? ? ? ? {

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

? ? ? ? ? ? ? };

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

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

? ? ? ? ? ? //進(jìn)一步簡化:假如方法中只有一行代碼

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

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

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

? ? ? ? }-

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

? ? ? ? {

? ? ? ? ? ? return a + b;

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

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

? ? ? ? public delegate string sayHelloDelegate();

? ? }


二、自定義泛型委托

1、為什么要使用泛型委托?

普通委托在數(shù)據(jù)類型上的限制是非常嚴(yán)格的,無法適應(yīng)需求變化

2、泛型委托定義:本質(zhì)上和泛型方法非常類似,泛型委托關(guān)聯(lián)的時(shí)候,可以是具體方法、匿名方法、Lambda表達(dá)式



/// <summary>

? ? /// 泛型委托

? ? /// </summary>

? ? class GenericDelegate

? ? {

? ? ? ? public void Test()

? ? ? ? {

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

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

? ? ? ? }

? ? ? ? //根據(jù)委托定義方法

? ? ? ? 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、問題引出:如果使用多個(gè)參數(shù),按照上述方法不得不定義很多這種泛型委托,非常麻煩

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

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

兩種方式:一種是有返回值Func<args>,一種是沒有返回值A(chǔ)ction<args>

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

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


Func<args>



/// <summary>

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

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

? ? /// </summary>

? ? class FunDelegateDemo

? ? {

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

? ? ? ? public void Test()

? ? ? ? {

? ? ? ? ? ? //【1】Func關(guān)聯(lián)具體方法

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

? ? ? ? ? ? //【2】Func直接使用Lambda表達(dá)式

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

? ? ? ? }

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

? ? ? ? {

? ? ? ? ? ? return a + b;

? ? ? ? }

? ? ? ? #endregion




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

? ? ? ? //問題:給定一個(gè)數(shù)組,從數(shù)組中指定位置抽取3個(gè)數(shù),求和,求積

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

? ? ? ? ? ? #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委托,將“運(yùn)算”本身作為方法參數(shù)

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

? ? ? ? ? ? {

? ? ? ? ? ? int result = nums[from];//把第一個(gè)值作為基數(shù)

? ? ? ? ? ? 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作為方法參數(shù),結(jié)合Lambda表達(dá)式

? ? ? ? ? ? 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委托沒有參數(shù),所以Action委托接收的是一個(gè)沒有返回值的方法

? ? /// </summary>

? ? class ActionDenlegateDemo

? ? {

? ? ? ? public void Test()

? ? ? ? {

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

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

? ? ? ? }

? ? }


Action委托與Func系列類似,有若干個(gè)重載方法,可以接收0-4個(gè)參數(shù),且返回值為void類型的方法


結(jié)論:泛型委托作為方法參數(shù),實(shí)際上傳遞的是一個(gè)具體的方法或者一個(gè)Lambda表達(dá)式(多態(tài)的一種表現(xiàn))

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容