c#的lamba表達(dá)式
之前已經(jīng)寫過一些關(guān)于委托還有事件的文章,今天就來介紹一下lambda表達(dá)式。
首先定義需要的函數(shù)以及委托
{
public delegate void DoNothingDelegate();
public delegate void StudyDelegate(int id, string name);
private void DoNothing()
{
Console.WriteLine("DoNothing");
}
private void Study(int id , string name)
{
Console.WriteLine($"{id} {name} 學(xué)習(xí) .Net高級(jí)班 " );
}
}
在.net farmwork 1.0,會(huì)這樣寫我們的匿名函數(shù)
public void Show()
{
{
//.netframework 1.0的寫法
DoNothingDelegate doNothing = new DoNothingDelegate(DoNothing);
StudyDelegate study = new StudyDelegate(Study);
}
}
在.netframework 2.0,會(huì)這樣寫匿名函數(shù), 增加了一個(gè)delegate關(guān)鍵字
{
DoNothingDelegate doNothing = new DoNothingDelegate (delegate ()
{
Console.WriteLine("DoNothing");
});
StudyDelegate study = new StudyDelegate( delegate (int id, string name)
{
Console.WriteLine($"{id} {name} 學(xué)習(xí) .Net高級(jí)班 ");
});
}
在.netframework3.0,去掉了delegate關(guān)鍵字了,在參數(shù)后增加了一個(gè)=> goes to
{
DoNothingDelegate doNothing = new DoNothingDelegate(() =>
{
Console.WriteLine("DoNothing");
});
StudyDelegate study = new StudyDelegate((int id, string name) =>
{
Console.WriteLine($"{id} {name} 學(xué)習(xí) .Net高級(jí)班 ");
});
}
在.netframework3.0后期,我們可以省略參數(shù)的信息
StudyDelegate study = new StudyDelegate((id, name) =>
{
Console.WriteLine($"{id} {name} 學(xué)習(xí) .Net高級(jí)班 ");
});
如果匿名方法體中只有一行代碼,可以省略方法題的大括號(hào)
StudyDelegate study = new StudyDelegate((id, name) =>Console.WriteLine($"{id} {name} 學(xué)習(xí) .Net高級(jí)班 "));
只有一個(gè)參數(shù)的時(shí)候,參數(shù)的小括號(hào)也可以省略掉。
public delegate void StudyNew(int id);
StudyNew study = id => Console.WriteLine($"{id} 學(xué)習(xí) .Net高級(jí)班 ");
如果方法返回值?
如果lambda表達(dá)式中只有一行代碼,且有返回值,可以省略return,
Func<int> retNum= () => 1;
lamba函數(shù)的本質(zhì)是什么?
這里使用ilspy進(jìn)行反編譯來看一下匿名方法的實(shí)現(xiàn)是怎么樣的
本質(zhì)上來說,其實(shí)就是一個(gè)方法--匿名方法, 在類里面會(huì)生成和lambad 表達(dá)式參數(shù)和返回值完全匹配的方法.
匿名類
有時(shí)候,可以需要?jiǎng)?chuàng)建一個(gè)臨時(shí)的類對(duì)象,保存數(shù)據(jù),方便使用。
一個(gè)普通的類對(duì)象
public class Student
{
public int Id { get; set; }
public int ClassId { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public string Description { get; set; }
public void Study()
{
Console.WriteLine($"{this.Id} {this.Name} 跟著老師學(xué)習(xí) .Net開發(fā)");
}
public void StudyQt()
{
Console.WriteLine($"{this.Id} {this.Name} 跟著老師學(xué)習(xí)C++ Qt");
}
}
當(dāng)創(chuàng)建一個(gè)普通的類對(duì)象的時(shí)候,這樣去創(chuàng)建一個(gè)類對(duì)象。
Student student = new Student()
{
Id = 1,
ClassId = 2,
Name = "張三",
Age = 20,
Description = "這是一個(gè)學(xué)生"
};
現(xiàn)在嘗試最原始的方法去創(chuàng)建一個(gè)匿名類,
object model = new
{
Id = 1,
Name = "小樓一夜聽春雨",
Age = 14,
Description = "魔刀丁鵬"
};
為什么可以定義一個(gè)匿名的對(duì)象?
因?yàn)镃#中所有的對(duì)象都繼承自O(shè)bject對(duì)象.
當(dāng)嘗試使用.去訪問其中的屬性就會(huì)報(bào)錯(cuò).
C#是強(qiáng)類型語言(編譯時(shí)決定類型),object是在編譯時(shí)確定類型,因?yàn)镺bject沒有Id等屬性,所以無法通過.去訪問其中的變量.
因此可以使用下面的方法去訪問我們的匿名對(duì)象中的屬性.
dynamic model1 = new
{
Id = 2,
Name = "天下第一的劍客",
Age = 18,
Description = "神劍山莊謝曉峰"
};
Console.WriteLine(model1.Id);
Console.WriteLine(model1.Age);
Console.WriteLine(model1.Amy); //報(bào)錯(cuò)
這里使用了dynamic關(guān)鍵字去避開了編譯器的檢查,會(huì)在運(yùn)行時(shí)檢查,運(yùn)行時(shí)決定類型.這個(gè)出現(xiàn)亂取的問題,導(dǎo)致程序崩潰.
有什么方法可以正確的取出想訪問的屬性,又可以避免訪問不存在的屬性那?
var關(guān)鍵字
var model2 = new
{
Id = 3,
Name = "天下第二的劍客",
Age = 16,
Description = "不會(huì)劍法的阿飛"
};
Console.WriteLine(model2.Id);
Console.WriteLine(model2.Name);
//Console.WriteLine(model2.Aniu); //報(bào)錯(cuò)!無法訪問不存在的變量
var類型就是弱類型的變量.
使用的注意事項(xiàng)?
- 不能在匿名類里面聲明方法,同時(shí)在聲明匿名類的屬性時(shí)候,就給定匿名類的屬性初始值.
- 不能給屬性重新賦值.
- var聲明的變量必須初始化,必須能推算出類型,也不允許作為方法的參數(shù)類型.
使用的建議?
- var配合匿名類型使用
- var偷懶,配合復(fù)雜類型時(shí)使用。
- 在不知道具體什么類型的時(shí)候就可以使用var來聲明
缺陷
在代碼閱讀的時(shí)候,不是很方便。
建議在大家寫代碼的時(shí)候,盡量明確類型。
擴(kuò)展方法
為什么需要擴(kuò)展方法?
- 擴(kuò)展:讓功能變得更加強(qiáng)大,讓不存在功能存在. ---新增邏輯處理
- 已經(jīng)存在方法,正常調(diào)用,擴(kuò)展的東西不影響已經(jīng)存在的方法
- 如果需求變更,需要支持另外的一個(gè)新的功能。
接著上面學(xué)生的用例,我們可以追加一些需求.
Student student1 = new Student()
{
Id = 1,
ClassId = 2,
Name = "張三",
Age = 20,
Description = "這是一個(gè)學(xué)生"
};
student1.Study();
student1.StudyQt();
如果要增加一個(gè)需求--學(xué)習(xí)嵌入式---直接增加方法.
傳統(tǒng)的方式對(duì)原有的類進(jìn)行結(jié)構(gòu)上的修改.
期望:既可以增加新的功能,歷史代碼不變.直接增加類,在新的類中去完成.
這里就可以使用擴(kuò)展方法來完成需求.
public static class MethodExtension
{
public static void StudyEmbedded(this Student student)
{
Console.WriteLine($"{student.Id} {student.Name} 跟著老師學(xué)習(xí)嵌入式開發(fā)");
}
}
program.cs
student.StudyEmbedded();
可以看到做的操作就是:
- 把類變成靜態(tài)類
- 把方法的第一個(gè)參數(shù)+this修飾
這樣就完成了一個(gè)擴(kuò)展方法.靜態(tài)方法的調(diào)用--可以像實(shí)例方法一樣去調(diào)用.
不用修改原有的任何類中的類,可以新增功能;
有哪些場景?
- 有新的需求來的時(shí)候--擴(kuò)展方法--保證歷史代碼功能
- 要應(yīng)用第三方的DLL庫(提供的功能不完善,我們自己需要升級(jí)下----dll,不能修改原有的代碼)擴(kuò)展方法
- 封裝幫助類庫
- asp.net core 中,到處都是擴(kuò)展方法--框架的設(shè)計(jì)--最小化設(shè)計(jì).提供一個(gè)最基本、最最最簡單的功能,提供給調(diào)用方.這種方式在使用的時(shí)候,如果想要增強(qiáng)功能,就可以擴(kuò)展. 好處:
- 盡可能簡化代碼
- 靈活分配,需要就擴(kuò)展什么.按需擴(kuò)展,不會(huì)有代碼冗余.
這里有個(gè)問題,我可以給任意類型寫擴(kuò)展方法嘛? 注意:擴(kuò)展object類型.
public static string SubObj(this object str, int len = 10)
{
if (str is null)
{
return string.Empty;
}
if (str.ToString().Length <= 10)
{
return str.ToString();
}
else
{
str = $"{str.ToString().Substring(0, len)}....";
return str.ToString();
}
}
program.cs文章來源:http://www.zghlxwxcb.cn/news/detail-839853.html
object o = "object 類型";
o.SubObj();
int i = 1;
i.SubObj();//可以
string sr = "你好";
sr.SubObj();
str.SubGeneric();
student.SubGeneric(); //隱患
總結(jié):文章來源地址http://www.zghlxwxcb.cn/news/detail-839853.html
- 擴(kuò)展的類型具有繼承性,擴(kuò)展父類,所有子類都擁有這個(gè)功能;擴(kuò)展的功能可能不適用一些具體的類型;但是仍然可以調(diào)用;可以造成一些類型的功能的污染;----慎用
- 不建議擴(kuò)展object,也不是很建議大家去泛型擴(kuò)展.
到了這里,關(guān)于CSharp的lambda表達(dá)式匿名類擴(kuò)展方法的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!