C# 6.0语法新特性体验(二)
之前我在文章通過Roslyn體驗C# 6.0的新語法中介紹了一些C# 6.0的語法特性,現在隨著Visual Studio 14 CTP3的發布,又陸續可以體驗一些新的特性了,這里簡單的介紹一下之前沒有介紹的新語法。
屬性表達式(Property Expressions)
我們常常會在類中寫一些通過函數生成的只讀屬性:
????class Point
????{
????????public int X { get; set; }
????????public int Y { get; set; }
????????public Point(int x, int y)
????????{
????????????this.X = x;
????????????this.Y = y;
????????}
????????public double Distance
????????{
????????????get { return Math.Sqrt((X * X) + (Y * Y)); }
????????}
????????public Point Move(int dx, int dy)
????????{
????????????return new Point(X + dx, Y + dy);
????????}
????}
現在,可以利用一個Lambda表達式簡化這一過程:
????????public double Distance => Math.Sqrt((X * X) + (Y * Y));
?
函數表達式(Method Expressions)
函數表達式和屬性表達式比較類似,使得我們可以通過Lambda表達式簡化成員函數。還是以上面的Point為例,Move函數可以簡化如下
????????public Point Move(int dx, int dy) => new Point(X + dx, Y + dy);
最后,再總結前文介紹的幾個新特性來一起來簡化Point類:
????class Point(int x, int y)
????{
????????public int X { get; set; } = x;
????????public int Y { get; set; } = y;
????????public double Distance => Math.Sqrt((X * X) + (Y * Y));
????????public Point Move(int dx, int dy) => new Point(X + dx, Y + dy);
????}
??
NULL檢查運算符(Monadic null checking)
這個是我非常喜歡的一個語法,例如我們要獲取一個Point序列的第一個點的X坐標,第一感覺會這么寫:
????int firstX = points.First().X;
但是,老鳥會告訴你,這兒沒有進行NULL檢查,正確的版本是這樣的:
????int? firstX = null;
????if (points != null)
????{
????????var first = points.FirstOrDefault();
????????if (first != null)
????????????firstX = first.X;
????}
正確倒是正確了,代碼取變得難讀多了。現在,在C# 6.0中,引入了一個 ?. 的運算符,前面的代碼可以改成如下形式:
????int? firstX = points?.FirstOrDefault()?.X;
從這個例子中我們也可以看出它的基本用法:如果對象為NULL,則不進行后面的獲取成員的運算,直接返回NULL
需要注意的是,由于"?."運算符返回的可以是NULL,當返回的成員類型是struct類型的時候,"?."和"."運算符的返回值類型是不一樣的。
????Point p = new Point(3, 2);
????Console.WriteLine(p.X.GetType() == typeof(int));????????//true
????Console.WriteLine(p?.X.GetType() == typeof(int?));????????//true
另外,除了"?."運算符外,還有一個"?[]"運算符,以使得我們可以寫出如下表達式:
????int? first = customers?[0].Orders.Count();
?
nameof表達式(Nameof expressions)
我們常常在反射或類似的技術中以字符串的形式使用屬性的名稱,拋開拼寫錯誤不談,當我們進行重構而修改屬性名稱的時候,由于字符串類型的屬性得不到編譯器檢查,修改相應的字符串屬性名稱是一件非常令人頭痛的事情,現在有了nameof,再也不用擔心拼錯屬性名稱了。
nameof運算符可以作用于變量、函數、類以及名字空間中,用于返回返回其名稱,例如:
????static void Main(string[] args)
????{
????????Console.WriteLine(nameof(Main));????????//輸出 "Main"
????}
當其參數是由"."運算符拼接起來的時候,只返回最后的名稱,例如:
????Console.WriteLine(nameof(ConsoleApplication1.Program));????????//輸出 "Program"
這個也可以理解,因為ConsoleApplication1.Program和Program本身就是等價的。
需要注意的是,由于C#允許函數重載,因此是存在同名函數的,例如:
????static void foo() { }
????static void foo(int x) { }
這樣就存在如下兩個問題:
這兩個問題只是體現在VisualStudio上,并不是語法的歧義,也不影響運行結果。在CodePlex中也有專門的文章討論它,目前的處理方式是:
?
catch和finally語句塊中支持await
在C# 5.0中引入了await運算符,可以方便我們執行異步運算。當時其并不能在catch和finally中使用,讓人有點意猶未盡的感覺。在C# 6.0放開了這一限制,使用更加方便了。
????try
????{
????????res = await Resource.OpenAsync(…);
????}
????catch (ResourceException e)
????{
????????await Resource.LogAsync(res, e);????//現在支持了
????}
????finally
????{
????????if (res != null) await res.CloseAsync(); //現在也支持了
????}
?
catch支持篩選條件了
catch支持篩選條件也是呼聲比較高的特性之一,現在終于可以省得重新再拋一次了
????try
????{
????????foo();
????}
????catch (Exception e ) if (e.HResult == 0x800000C)
????{
????????//do something
????}
?
其它未支持的特性
我這里只是介紹目前可以使用的新特性,我這里試出來的貌似可以補充的就這么多了。其它還有一些尚未推出的特性等下次有了更新的版本再做介紹。感興趣的朋友可以看看官方的特性實現狀態文檔:http://roslyn.codeplex.com/wikipage?title=Language%20Feature%20Status&referringTitle=Home。目前比較期待的新特性是String interpolation和模式匹配,尤其是模式匹配,希望能早日體驗一下。
另外,目前還沒有發現什么BCL方面的更新介紹,雖然BCL已經比較完善了,但感覺這次更新粒度蠻大的,估計至少會有一些基礎庫的補充的。
轉載于:https://www.cnblogs.com/TianFang/p/3928172.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的C# 6.0语法新特性体验(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 三维人脸重建:精读3dmm.py
- 下一篇: 基于ArcEngine与C#的鹰眼地图实