使用ILSpy探索C#7.0新增功能点
第一部分:
C#是一種通用的,類型安全的,面向?qū)ο蟮木幊陶Z言。有如下特點(diǎn):
(1)面向?qū)ο?#xff1a;c# 是面向?qū)ο蟮姆独囊粋€(gè)豐富實(shí)現(xiàn), 它包括封裝、繼承和多態(tài)性。C#面向?qū)ο蟮男袨榘?#xff1a;
統(tǒng)一的類型系統(tǒng)
類與接口
屬性、方法、事件
(2)類型安全:C#還允許通過dynamic關(guān)鍵字動(dòng)態(tài)指定類型。 但是,C#仍然是一個(gè)主要的靜態(tài)類型語言。之所以是一種強(qiáng)類型的語言,是因?yàn)樗念愋鸵?guī)則是非常嚴(yán)格的,例如,不能夠使用一個(gè)float類型的參數(shù)去調(diào)用一個(gè)解釋int 類型的函數(shù),除非顯式的把float轉(zhuǎn)換為int ,這樣有助于防止編碼錯(cuò)誤。
(3)內(nèi)存管理:C#依賴運(yùn)行時(shí)的自動(dòng)內(nèi)存管理,它的公共語言運(yùn)行庫有一個(gè)垃圾回收器,在合適非時(shí)間回收不再引用的對象所占的空間,這就釋放了程序員手動(dòng)釋放對象的內(nèi)存。C#并沒有消除指針,它只是使大多數(shù)編程任務(wù)不需要使用指針,對于性能要求高的地方,還是可以使用指針的,但是只允許在顯式標(biāo)記為不安全的代碼塊中使用。
(4)C#和CLR:C#是依賴runtime提供的內(nèi)存管理和異常處理,CLR允許開發(fā)者使用不同的語言建立應(yīng)用程序。C#是被編譯成托管代碼的幾種托管語言之一。托管代碼以中間語言或IL表示。CLR把IL轉(zhuǎn)換成機(jī)器的本地代碼,例如X86或X64,通常就在此之前執(zhí)行,這被稱為即時(shí)(Just-In-Time,JIT)編譯。 提前時(shí)間編譯也可用于改善大型程序集的啟動(dòng)時(shí)間,或資源受限的設(shè)備。元數(shù)據(jù)的存在允許,程序集引用其他程序集中的類型而不需要額外的文件。
(5)CRL和 .Net Framework的關(guān)系
.NET Framework由CLR和大量的庫組成;該類庫中包含核心類庫(也就是基礎(chǔ)類庫BCL)和應(yīng)用類庫,應(yīng)用類庫又依賴核心類庫
?
婆婆媽媽說了這么多,我相信大家都知道,好了,下面我們通過代碼來看看C#7.0到底有哪些讓你拍手叫好的地方。
第二部分:C#7.0新增的功能
(1)數(shù)字字面量的提升:
C#7中的數(shù)字文字可以包含下劃線以提高可讀性,這些被稱為數(shù)字分隔符,并被編譯器忽略。
代碼如下:
運(yùn)行結(jié)果:
注意:二進(jìn)制文字可以用0b前綴指定。
所以見到這種寫法你不要驚訝,只是為了提高可讀性。
(2)Out variables and discards(接收out變量和丟棄out變量)
代碼:
以前我們的寫法:
?
現(xiàn)在C#7.0中可以這樣寫:
我們不需要在外面先定義好要接收值的變量,而是直接在里面寫,是不是代碼更簡潔,另外一個(gè)有趣的地方是,當(dāng)一個(gè)方法要返回多個(gè)值的時(shí)候,我們可以使用 out _,來選擇性的接收返回來的值,在上面圖中的代碼中,方法SomeBigMethod返回四個(gè)值,但是我們在接收它返回來的值時(shí),可以使用out _不接收返回來的值,而使用out int x,來接收返回來的值,是不是很靈活。
代碼運(yùn)行結(jié)果如下:
ILSpy結(jié)果:
// Methods
? ? .method private hidebysig static?
? ? ? ? void Main (
? ? ? ? ? ? string[] args
? ? ? ? ) cil managed?
? ? {
? ? ? ? // Method begins at RVA 0x2050
? ? ? ? // Code size 49 (0x31)
? ? ? ? .maxstack 4
? ? ? ? .entrypoint
? ? ? ? .locals init (
? ? ? ? ? ? [0] int32,
? ? ? ? ? ? [1] bool,
? ? ? ? ? ? [2] int32,
? ? ? ? ? ? [3] int32,
? ? ? ? ? ? [4] int32,
? ? ? ? ? ? [5] int32
? ? ? ? )
? ? ? ? // (no C# code)
? ? ? ? IL_0000: nop
? ? ? ? // bool successful = int.TryParse("123", out result);
? ? ? ? IL_0001: ldstr "123"
? ? ? ? IL_0006: ldloca.s 0
? ? ? ? IL_0008: call bool [System.Runtime]System.Int32::TryParse(string, int32&)
? ? ? ? IL_000d: stloc.1
? ? ? ? // SomeBigMethod(out int _, out int _, out int x, out int _);
? ? ? ? IL_000e: ldloca.s 3
? ? ? ? IL_0010: ldloca.s 4
? ? ? ? IL_0012: ldloca.s 2
? ? ? ? IL_0014: ldloca.s 5
? ? ? ? IL_0016: call void ConsoleApp1.Program::SomeBigMethod(int32&, int32&, int32&, int32&)
? ? ? ? // (no C# code)
? ? ? ? IL_001b: nop
? ? ? ? // Console.WriteLine(x);
? ? ? ? IL_001c: ldloc.2
? ? ? ? IL_001d: call void [System.Console]System.Console::WriteLine(int32)
? ? ? ? // (no C# code)
? ? ? ? IL_0022: nop
? ? ? ? // Console.WriteLine(result);
? ? ? ? IL_0023: ldloc.0
? ? ? ? IL_0024: call void [System.Console]System.Console::WriteLine(int32)
? ? ? ? // (no C# code)
? ? ? ? IL_0029: nop
? ? ? ? // Console.ReadKey();
? ? ? ? IL_002a: call valuetype [System.Console]System.ConsoleKeyInfo [System.Console]System.Console::ReadKey()
? ? ? ? IL_002f: pop
? ? ? ? // (no C# code)
? ? ? ? IL_0030: ret
? ? } // end of method Program::Main
(3)Patterns
作用:你可以使用is運(yùn)算符來引入一個(gè)變量,這個(gè)變量被稱為模式變量。不明白,看個(gè)例子就明白了。
代碼如下:
解析:x is string s 的作用是:如果x 可以被轉(zhuǎn)換為string 轉(zhuǎn)換后的值賦值給了s ,所以輸出的結(jié)果就是字符串的長度。
其中switch的聲明也支持這種模式,而且還可以使用when子句指定條件,代碼如下:
?運(yùn)行結(jié)果:
解析:Foo2(9)傳遞過來的是9,是int 類型,所以就進(jìn)入到第一個(gè)case 子句中,所以最終輸出的結(jié)果就是:It is an int !,這個(gè)解釋給零分,下面我們通過ILSpy看看這種語法糖到底是什么東東,如下圖所示:
我就不解釋了,大家一看就明白,是不是想拍下大腿,TM原來就這么簡單!!!
(4)本地方法(Local methods)
作用:A local method is a method declared inside another function。這里我給出英文,因?yàn)檫@種方式給出是最準(zhǔn)確的,中文翻譯出來就TM看不懂了。
運(yùn)行結(jié)果:
解析:? 定義了一個(gè)本地方法,返回值類型是int 傳入的參數(shù)是value ,返回值是:value*value*value+i
Cube(2),調(diào)用傳入值2 ,所以最終計(jì)算出來的值為 2*2*2+9=17
注意:本地方法僅對包含函數(shù)可見,并且可以使用包含該本地方法的變量。
ILSpy反編譯的結(jié)果:
可以看出在調(diào)用Cube(2),最終被編譯成Cube(2,ref xx)這樣一個(gè)方法,但看不到?<WriteCubes>g__Cube|3_0方法的內(nèi)部實(shí)現(xiàn)。
(5)c# 6 介紹了方法的 "fat-箭頭" 語法, 可以用在只讀、屬性、運(yùn)算符和索引器。c# 7 將此擴(kuò)展到構(gòu)造函數(shù)、讀/寫屬性、終結(jié)器
代碼:
ILSPy代碼結(jié)果:
?(6)對于 c# 7, 可能最顯著的改進(jìn)是顯式元組支持
作用:元組提供了一種簡單的方法來存儲一組相關(guān)值
代碼:
運(yùn)行結(jié)果:
解析:?var bob = ("Bob", 23);定義了一個(gè)元組,可以使用bob.Item1來訪問第一個(gè)參數(shù),可以使用bob.Item2來訪問第二參數(shù),但問題來了,為什么可以這樣來訪問???
ILSpy結(jié)果:
可以看到,元組其實(shí)是一個(gè)ValueTuple<,>的泛型類型,其中string int 是有你的值的類型決定的,那為什么可以使用Item1和Item2來訪問對應(yīng)的值呢?
?
首先Item1和Item2是人家?ValueTuple<T1, T2> 中定義的,那為什么我訪問Item1就是"Bob",那是因?yàn)樵跇?gòu)造函數(shù)中,把"Bob"賦值給了Item1,所以明白了吧。
另外可以看出元組是一個(gè)結(jié)構(gòu)體,屬于值類型的。講到這里還沒有講完元組的點(diǎn),由于編譯器的魔力, 元組元素可以被命名為下面的形式:
ILSpy結(jié)果:
借助于元組,函數(shù)可以返回多個(gè)參數(shù),而不需要借助于out 參數(shù):
運(yùn)行結(jié)果:
ILSpy結(jié)果:
注意:元組隱含地支持反解析模式, 因此它們可以很容易地被分解成單個(gè)變量。我們可以重寫前面的主方法使 GetFilePosition 返回的元組被分配給兩個(gè)局部變量:row和cloum:
?
運(yùn)行結(jié)果:
ILSPy結(jié)果:(結(jié)果和上面的一樣)
好了,元組就講到這里,接下讓我們看看如何拋出異常。
(7)拋出異常
功能:在C#7之前,throw總是要被聲明,現(xiàn)在它可以作為一個(gè)表達(dá)式出現(xiàn)在一個(gè)函數(shù) 體中,而且也可以出現(xiàn)在三元表達(dá)式中。
?ILSpy結(jié)果:
(8)字符串的插值
直接上代碼:
如果要多行顯示,可以這樣寫:
注意:$符一定要在@符號之前。
ILSpy結(jié)果:
簡單我就不多說了,繼續(xù)下面的知識點(diǎn)。
(9)異常篩選器(Exception filters)
作用:允許你在catch中應(yīng)用一個(gè)條件。
(10)引用本地變量Ref Locals
作用:C#7.0中引入了一個(gè)極為重要的點(diǎn),借此,你可以定義一個(gè)本地變量,這個(gè)變量引用一個(gè)數(shù)組中的元素或者對象中的字段。
代碼:
注意:Ref Locals?必須是數(shù)組中的一個(gè)元素、字段、或者本地變量,不能是屬性。它通常與 ref returns 一起使用。
?
運(yùn)行結(jié)果:
解析:ref int age 標(biāo)注這個(gè)變量時(shí)就是一個(gè)引用類型的變量。
(11)Ref Returns
?作用:你可以在一個(gè)方法中返回一個(gè) ref local,這種方式被叫做ref return
代碼:
運(yùn)行結(jié)果:
解析:private static ref int GetX() 其實(shí)是一個(gè) 返回值為int32&(就是一個(gè)標(biāo)記了內(nèi)存指針的INT32類型)的方法,也就是返回一個(gè)地址,這樣我再修改值后其實(shí)就是修改的x的值。
ILSpy結(jié)果:
注意:ldsflda int32 :是把一個(gè)靜態(tài)字段x的地址壓入到棧中,ret,然后返回,在Main方法中,調(diào)用上面的方法后,從棧頂把值取出來,存儲到本地變量列表中索引位置0里面。
然后取本地變量中索引位置為0的值,并壓入棧中,注意重點(diǎn)來了,stind.i4 是把 ldc.i4.s 9 值 的地址存儲下來,這樣就改變了x的值。所以這個(gè)int32&其實(shí)就是一個(gè)變量的地址,也就是我們通常所說的指針。
?
好了講到這里基本上C#7.0新增的功能就講的差不多了,后續(xù)我會繼續(xù)補(bǔ)充C#7.0新的知識點(diǎn),希望對你有幫助!謝謝。
最后,歡迎大家加入到我的C#+.Net Core英文書籍翻譯群,我會不定期通過博客更新翻譯的英文資料,希望得到最新的C#知識,同時(shí)對你我也有所提高。?
參考書籍:《C 7.0 in a Nutshell 7th Edition》
相關(guān)文章:
C# 這些年來受歡迎的特性
C# 7編程模式與實(shí)踐
C# 7.1、7.2特性追蹤
C# 7.2和8.0路線圖
原文地址:https://www.cnblogs.com/runningsmallguo/p/8972678.html
.NET社區(qū)新聞,深度好文,歡迎訪問公眾號文章匯總 http://www.csharpkit.com
總結(jié)
以上是生活随笔為你收集整理的使用ILSpy探索C#7.0新增功能点的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: .NET Core 在中国的现状调研
- 下一篇: C#编译器优化那点事