vs2008中C#3.0语言的新特性
看了YJingLee's Blog的文章,收獲很大,以下文章轉(zhuǎn)自http://www.cnblogs.com/lyj/archive/2008/01/08/1030525.html
?
總體來(lái)說(shuō),Visual Studio 2008和.NET 3.5是建立在.NET2.0核心的基礎(chǔ)之上,.NET2.0核心本身將不再變化(如果不了解.NET2.0的朋友,請(qǐng)參看MSDN或者一些經(jīng)典的書籍),C# 3.0新語(yǔ)言特性在.NET2.0基礎(chǔ)上進(jìn)行了改進(jìn),這些改進(jìn)的功能可以大大簡(jiǎn)化我們編寫程序。關(guān)于C# 3.0新語(yǔ)言特性在博客園里的很多朋友都介紹了,我在這里簡(jiǎn)單介紹一下,記錄自己所學(xué)的東西,也為后面的LINQ打下基礎(chǔ)。
C# 3.0新語(yǔ)言特性和改進(jìn)包括:
- 自動(dòng)屬性(Auto-Implemented Properties)
- 隱含類型局部變量(Local Variable Type Inference)
- 匿名類型(Anonymous Types)
- 對(duì)象與集合初始化器(Object and Collection Initializers)
- 擴(kuò)展方法(Extension Methods)
- Lambda表達(dá)式和Lambda表達(dá)式樹(shù) (Lambda Expression and Lambda Expression Trees)
?
自動(dòng)屬性可以避免原來(lái)這樣我們手工聲明一個(gè)私有成員變量以及編寫get/set邏輯,在VS2008中可以像下面這樣編寫一個(gè)類,編譯器會(huì)自動(dòng)地生成私有變量和默認(rèn)的get/set 操作。你也可以分別定義get和set的“protected”等訪問(wèn)級(jí)別。
在.Net2.0框架下,我們可以這樣寫一個(gè)User類:
public class User { private int _id; private string _name; private int _age; public int Id { get { return _id; } set { _id = value; } } public string Name { get { return _name; } set { _name = value; } } public int Age { get { return _age; } set { _age = value; } } }現(xiàn)在,可以這樣簡(jiǎn)化:
public class User { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } }像上面這樣的空的get/set屬性的話,它會(huì)自動(dòng)為你在類中生成一個(gè)私有成員變量,對(duì)這個(gè)變量實(shí)現(xiàn)一個(gè)公開(kāi)的getter 和setter。我們可以使用.NET開(kāi)發(fā)環(huán)境所提供的ildasm.exe(IL代碼反匯編器)工具來(lái)分析程序集或者模塊的內(nèi)容。我就不貼圖了。
?
C#3.0引進(jìn)了var這個(gè)新關(guān)鍵字,在聲明局部變量時(shí)可用于替代原先的類型名,即當(dāng)一個(gè)變量聲明標(biāo)識(shí)為var類型并且該范圍域中沒(méi)有var名稱類型存在,那么這個(gè)聲明就稱為隱含類型局部變量。如下(等同于//后面的顯式聲明):
var i = 5;//int var j = 23.56;//double var k = "C Sharp";//string var x;//錯(cuò)誤 var y = null;//錯(cuò)誤 var z = { 1, 2, 3 };//錯(cuò)誤在調(diào)試狀態(tài)下,編譯器解釋如下
隱含類型局部變量要點(diǎn)
匿名類型(Anonymous Types)
匿名類型允許定義行內(nèi)類型,無(wú)須顯式定義類型。常和var配合使用來(lái)聲明匿名類型。
var p1 = new { Id = 1, Name = "YJingLee", Age = 22 };//屬性也不需要申明 var p2 = new { Id = 2, Name = "XieQing", Age = 25 }; p1 = p2;//p1,p2結(jié)構(gòu)相同,可以互相賦值在這里編譯器會(huì)認(rèn)為p1,p2相當(dāng)于:
public class SomeType { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } }那么數(shù)組怎么定義呢?使用"new[]"關(guān)鍵字來(lái)聲明數(shù)組,加上數(shù)組的初始值列表。像這樣:
var intArray = new[] { 2, 3, 5, 6 }; var strArray = new[] { "Hello", "World" }; var anonymousTypeArray = new[] { new { Name = "YJingLee", Age = 22 }, new { Name = "XieQing", Age = 25 } }; var a = intArray[0]; var b = strArray[0]; var c = anonymousTypeArray[1].Name;匿名類型要點(diǎn)
?
對(duì)象初始化器 (Object Initializers) :
.NET2.0框架中的類型非常依賴于屬性。當(dāng)生成對(duì)象實(shí)例和使用新的類型時(shí),在.Net2.0時(shí)候我們像這樣寫:
User user = new User(); user.Id = 1; user.Name = "YJingLee"; user.Age = 22;在VS2008中,編譯器會(huì)自動(dòng)地生成合適的屬性setter代碼,使得原來(lái)幾行的屬性賦值操作可以在一行完成。我們可以這樣簡(jiǎn)化:像這樣,對(duì)象初始化器由一系列成員對(duì)象組成,其對(duì)象必須初始化,用逗號(hào)間隔,使用{}封閉。
User user = new User { Id = 1, Name = "YJingLee", Age = 22 };又例如,我把二個(gè)人加到一個(gè)基于泛型的類型為User的List集合中:
List<User> user = new List<User>{ new User{Id=1,Name="YJingLee",Age=22}, new User{Id=2,Name="XieQing",Age=25}, };如果有相同名字和類型的兩個(gè)對(duì)象初始化器將會(huì)產(chǎn)生相同的實(shí)例,可以相互賦值。例如:
User user = new User { Id = 1, Name = "YJingLee", Age = 22 }; User user2 = new User { Id = 2, Name = "XieQing", Age = 25 }; user = user2;除了在初始化類時(shí)設(shè)置簡(jiǎn)單的屬性值外,對(duì)象初始化器特性也允許我們?cè)O(shè)置更復(fù)雜的嵌套(nested)屬性類型。例如我們可以在上面定義的User類型同時(shí)擁有一個(gè)屬于Address類型的叫“Address”的屬性:
User user = new User { Id = 1, Name = "YJingLee", Age = 22, Address = new Address { City = "NanJing", Zip = 21000 } };集合初始化器(Collection Initializers):
集合初始化器由一系列集合對(duì)象組成,用逗號(hào)間隔,使用{}封閉。
集合初始化器可以簡(jiǎn)化把幾個(gè)對(duì)象一起添加到一個(gè)集合,編譯器會(huì)自動(dòng)為你做集合插入操作。例如我把七個(gè)數(shù)加到一個(gè)基于泛型的類型為int的List集合中
對(duì)象與集合初始化器要點(diǎn)
?
擴(kuò)展方法(Extension Methods)
往往我們需要對(duì)CLR類型進(jìn)行一些操作,但苦于無(wú)法擴(kuò)展CLR類型的方法,只能創(chuàng)建一些helper方法,或者繼承類。我們來(lái)修改上面的User類:
public class User { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } public string Read() { return "Id:" + Id + "姓名:" + Name + "年齡:" + Age; } }然后調(diào)用
var user = new { Id = 1, Name = "YJingLee", Age = 22 }; var str = user.Read();現(xiàn)在有了擴(kuò)展方法就方便多了。
擴(kuò)展方法允許開(kāi)發(fā)人員往一個(gè)現(xiàn)有的CLR類型的公開(kāi)契約(contract)中添加新的方法,而不用生成子類或者重新編譯原來(lái)的類型。擴(kuò)展方法有助于把今天動(dòng)態(tài)語(yǔ)言中流行的對(duì)duck typing的支持之靈活性,與強(qiáng)類型語(yǔ)言之性能和編譯時(shí)驗(yàn)證融合起來(lái)。——引用Scott博文
擴(kuò)展方法是可以通過(guò)使用實(shí)例方法語(yǔ)法調(diào)用的靜態(tài)方法。效果上,使得附加的方法擴(kuò)展已存在類型和構(gòu)造類型成為可能。他可以對(duì)現(xiàn)有類功能進(jìn)行擴(kuò)充,從而使該類型的實(shí)例具有更多的方法(功能)。
擴(kuò)展方法允許我們?cè)诓桓淖冊(cè)创a的情況下擴(kuò)展(即添加不能修改)現(xiàn)有類型中的實(shí)例方法。
擴(kuò)展方法給我們一個(gè)怎樣的思路呢?我們一步一步做一下!
首先聲明擴(kuò)展方法:通過(guò)指定關(guān)鍵字this修飾方法的第一個(gè)參數(shù)。注意擴(kuò)展方法僅可聲明在靜態(tài)類中。擴(kuò)展方法具備所有常規(guī)靜態(tài)方法的所有能力,可以使用實(shí)例方法語(yǔ)法來(lái)調(diào)用。接著就可以調(diào)用擴(kuò)展方法了。下面通過(guò)一個(gè)具體的實(shí)例分析一下:
例如我們要檢查一個(gè)字符串變量是否是合法的電子郵件地址?在.Net2.0框架下像這樣:
而使用擴(kuò)展方法的話,我可以添加“IsValidEmailAddress()”方法到string類本身中去,該方法返回當(dāng)前字符串實(shí)例是否是個(gè)合法的字符串。
if (email.IsValidEmailAddress()) { Response.Write("YJingLee提示:這是一個(gè)正確的郵件地址"); }我們是怎么把這個(gè)IsValidEmailAddress()方法添加到現(xiàn)有的string類里去的呢?先定義一個(gè)靜態(tài)類,再定義“IsValidEmailAddress”這個(gè)靜態(tài)的法來(lái)實(shí)現(xiàn)的。
public static class Extensions//靜態(tài)類 { public static bool IsValidEmailAddress(this string s) //靜態(tài)方法和this { Regex regex = new Regex(@"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$"); return regex.IsMatch(s); } }注意,上面的靜態(tài)方法在第一個(gè)類型是string的參數(shù)變量前有個(gè)“this”關(guān)鍵詞,這告訴編譯器,這個(gè)特定的擴(kuò)展方法應(yīng)該添加到類型為“string”的對(duì)象中去。然后在IsValidEmailAddress()方法實(shí)現(xiàn)里,我可以訪問(wèn)調(diào)用該方法的實(shí)際string實(shí)例的所有公開(kāi)屬性/方法/事件,取決于它是否是合法電子郵件地址來(lái)返回true/false。
擴(kuò)展方法不僅能夠應(yīng)用到個(gè)別類型上,也能應(yīng)用到.NET框架中任何基類或接口上。即可用于整個(gè).NET框架豐富的可組合的框架層擴(kuò)展。
擴(kuò)展方法要點(diǎn)
?
Lambda表達(dá)式
我們從“所有字符串查找包含YJingLee子字符串”說(shuō)起。在C# 2.0中,匿名方法允許我們以內(nèi)聯(lián)的方式來(lái)實(shí)現(xiàn)委托實(shí)例,它提供強(qiáng)大的函數(shù)式編程語(yǔ)言,但是標(biāo)記顯得相當(dāng)?shù)娜唛L(zhǎng)和帶有強(qiáng)制性。我們使用C# 2.0 中的匿名方法查找,代碼如下:
var inString = list.FindAll(delegate(string s) { return s.Indexof("YJingLee") >= 0; });現(xiàn)在可以使用C# 3.0帶來(lái)的Lambda表達(dá)式允許我們使用一種更接近人的思維、更自然的方式來(lái)實(shí)現(xiàn)類似于匿名方法同樣的效果,看下面的代碼多么簡(jiǎn)潔:
var inString = list.FindAll(s => s.Indexof("YJingLee") >= 0);Lambda表達(dá)式格式:(參數(shù)列表)=>表達(dá)式或語(yǔ)句塊
具體意義:定義Lambda接受參數(shù)列表,運(yùn)行表達(dá)式或語(yǔ)句塊返回表達(dá)式或語(yǔ)句塊的值傳給這個(gè)參數(shù)列表。
Lambda表達(dá)式參數(shù)類型可以是隱式類型或顯式類型。在顯式列表中,每個(gè)參數(shù)的類型是顯式指定的,在隱式列表中,參數(shù)的類型由Lambda表達(dá)式出現(xiàn)的語(yǔ)境自動(dòng)推斷類型。
Lambda表達(dá)式的參數(shù)列表可以有一個(gè)或多個(gè)參數(shù),或者無(wú)參數(shù)。在有單一的隱型參數(shù)的lambda表達(dá)式中,圓括號(hào)可以從參數(shù)列表中省略。
例如:
下面看這個(gè)例子:
在前面的帖子中,我們寫了一個(gè)User類及增加了2個(gè)人,接下來(lái),我們使用由LINQ提供的新的Where和Average方法來(lái)返回集合中的人的一個(gè)子集,以及計(jì)算這個(gè)集合中的人的平均年齡:
效果圖如下:
對(duì)這個(gè)Lambda表達(dá)式做個(gè)簡(jiǎn)要分析:
var resultsdelegate = user.Where(delegate(User p) { return p.Name == "YJingLee";// 返回一個(gè)布爾值 }); var averagedelegate = user.Average(delegate(User p) { return p.Age; });Lambda表達(dá)式L可以被轉(zhuǎn)換為委托類型D,需要滿足以下條件:
L的參數(shù)類型要與D的參數(shù)個(gè)數(shù)相等,類型相同,返回類型相同,無(wú)論是表達(dá)式,還是語(yǔ)句塊。注意隱式類型要參與類型辨析。
Lambda表達(dá)式樹(shù)
Lambda表達(dá)式樹(shù)允許我們像處理數(shù)據(jù)(比如讀取,修改)一樣來(lái)處理Lambda表達(dá)式。我以一個(gè)例子簡(jiǎn)單說(shuō)明:
Expression<Func<int, bool>> filter = n => (n * 3) < 5; BinaryExpression lt = (BinaryExpression)filter.Body; BinaryExpression mult = (BinaryExpression)lt.Left; ParameterExpression en = (ParameterExpression)mult.Left; ConstantExpression three = (ConstantExpression)mult.Right; ConstantExpression five = (ConstantExpression)lt.Right; var One = filter.Compile(); Console.WriteLine("Result: {0},{1}", One(5), One(1)); Console.WriteLine("({0} ({1} {2} {3}) {4})", lt.NodeType, mult.NodeType, en.Name, three.Value, five.Value);效果圖如下:
Lambda表達(dá)式和Lambda表達(dá)式樹(shù)要點(diǎn)
????? 現(xiàn)在基本看完了和LINQ有關(guān)的C#新特性,其實(shí)現(xiàn)在看來(lái)微軟雖然進(jìn)行了很多改進(jìn),可以減少很多代碼量,但這些改進(jìn)是建立在降低代碼的可讀性上的,如果習(xí)慣之前版本的程序員會(huì)覺(jué)得代碼難以閱讀了。?
轉(zhuǎn)載于:https://www.cnblogs.com/millen/archive/2009/02/12/1388922.html
總結(jié)
以上是生活随笔為你收集整理的vs2008中C#3.0语言的新特性的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: asp.net下向数据库存储和读取图片示
- 下一篇: C# default關鍵字