国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

從反編譯的角度去觀察C#6.0

2019-11-14 13:57:38
字體:
來源:轉載
供稿:網友

1. 自動屬性初始化 (Initializers for auto-PRoperties)

1.1 C#6.0 之前的寫法

public class FirstExperience{   private string _stringAutoProp = "自動初始化屬性";   public string StringAutoProp   {      get{ return _stringAutoProp; }      set{ _stringAutoProp = value; }   }}

1.2 C#6.0 中的寫法

public class FirstExperience{   public string StringAutoProp { get; set; } = "自動初始化屬性";}

1.3 反編譯效果


從反編譯中我們發現多了個私有字段this.<StringAutoProp>k__BackingField;并在默認的構造函數中將“自動初始化屬性”賦值給了這個字段,那么可以推斷出IL中肯定會有這個匿名字段的定義,讓我們再來看看IL中的體現:

用上面的兩張圖我們可以得出以下結論

其實自動初始化屬性就是在CLR中體現就是創建私有的匿名字段,然后在構造函數中為這個匿名屬性賦值,而屬性的getSet方法其實就是在操作這個匿名屬性。

2. 只讀屬性的初始化(Getter-only auto-properties)

2.1 C#6.0 之前的寫法

public FirstExperience(int id){    _id = id;}private readonly int _id;public int ID{    get { return _id; }}

2.2 C#6.0 中的寫法

public int ReadonlyProp { get; }public FirstExperience(int _readonlyProp){    ReadonlyProp = _readonlyProp;}

2.3 反編譯效果


從反編譯的結果我們看到構造函數中將傳進來的_readonlyProp賦值給this.<ReadonlyProp>k__BackingField字段,而屬性的get方法操作的就是這個由編譯器生成的字段,而在ReadonlyProp屬性的get方法中打了CompilerGenerated這個特性標簽,這個標簽其實就是區分編譯器生成的元素與用戶生成的元素,關于這個特性請移步到此。由此可以推斷IL中所做的操作與自動初始化屬性一致

3. 用Lambda作為函數體 (Expression bodies on method-like members)

3.1 C# 6.0 之前的寫法

 public override string ToString(){    return string.Format("{0}",StringAutoProp);}

3.2 C# 6.0 寫法

public override string ToString() => string.Format("{0}", StringAutoProp);

在6.0 語法中我們看到可以使用lambda表達式直接作為函數體,那么編譯器到底為我們做了什么呢?

3.3 反編譯效果

從反編譯中我們可以看出編譯器編譯的時候把lambda函數直接編譯成方法體,那么再看看IL的區別了。

從上面兩張圖中可以看出除了標注堆棧標注刻度不同以外,看不出有什么差別。我也不是太明白這個地方,求園內的大牛解釋解釋!

4. 空值判斷 (Null-conditional Operators)

4.1 惡心的寫法

if(xxx !=null){    xxx.ToString();}

這種寫法相信有非常多的朋友用過,經常為了一個是否為空的問題搞得代碼非常難看,
舉個栗子:我們需要獲取集合或者是字符喘的長度

if(parem!=null){    return parem.Length;}return null;

這樣的寫法實在太惡心了,在6.0語法中我們可以這么寫

public int? GetListCount(List<int> list){    return list?.Count();}

4.2 實際應用的栗子

在實際應用中,經常會用到委托,而在之前我們需要調用委托時則需要判斷委托是否為空如下代碼:

public void Test(TestNew test){    if (test != null)    {        test.Invoke();    }}

對于強迫癥的我來說這樣太惡心了,于是乎利用6.0的語法開始改造

public void Test1(TestNew test){    test?.Invoke();}

4.3 根據上面的栗子進行反編譯

從上圖反編譯效果可以看到兩個方法基本沒有差別,接下來看看IL中有什么差別:

上圖為6.0語法委托調用的IL圖,發現核心還是brtrue.s做IF判斷決定執行流

5. nameof表達式 (nameof expressions)

5.1 在實際項目的方法中我們經常需要這樣去做參數判斷

public void MyMethod(string name){    if (string.IsNullOrEmpty(name))    {        throw new ArgumentNullException("name");    }}

上面代碼中的name是我們手寫的字符串,在給參數name改名時經常會忘記改下面的字符串name,然而 6.0 解決了這個問題:

public void MyMethod(string name){    if (string.IsNullOrEmpty(name))    {        throw new ArgumentNullException(nameof(name));    }}

5.2 nameof的反編譯

上圖中nameof(name)被替換成了字符串name,就如同常量一樣。繼續來看看IL做了什么:

從IL中我們可以看到它是直接ldstr,既不是反射也不是拿變量的內存值,在實際運用中有時候我們會通過Type來獲取他的類名或者是直接寫死的但是這樣通過反編譯后會發現Type.Name在IL中其實是通過反射來獲取,而直接寫死的方式,在IL中其實就是定義一個變量到堆棧中然后再引用進去。
nameof(name)具有這兩種的的有點,靈活而且相對于type和寫死的方式性能更高了。

6. 小結

其實6.0中還有很多新的語法糖,在這里就不一一介紹了,等不忙了,我在把其他的新的語法糖寫出來

非常感謝您花時間讀完這篇文章,如果您覺得此文不錯,請點一下“推薦”按鈕,您的“推薦”就是對我最大的鼓勵以及不懈努力的肯定。
本文版權歸作者和博客園所有,來源網址:http://www.survivalescaperooms.com/Wesley-Zen/歡迎各位轉載,轉載文章之后必須在文章頁面明顯位置給出作者和原文連接,否則保留追究法律責任的權利以及小小的鄙視。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 辽阳县| 兴安盟| 大同县| 清水河县| 寻甸| 洪洞县| 巩义市| 河池市| 嘉定区| 禄丰县| 柯坪县| 浠水县| 甘谷县| 科尔| 华安县| 百色市| 昌宁县| 宜良县| 莱芜市| 宜兴市| 定日县| 扶沟县| 曲阜市| 柘城县| 定兴县| 通江县| 泗洪县| 浏阳市| 西青区| 宜春市| 山东| 赤城县| 和静县| 江津市| 固原市| 江油市| 衡阳市| 溆浦县| 清水县| 综艺| 远安县|