探索C#之6.0語法糖剖析

自動屬性默認初始化

使用方法:

public string Name { get; set; } = "Hello World";

編譯器生成代碼:

public class Customer 
{
 [CompilerGenerated] 
private string kBackingField = "<span style="color: #993300;">hello world</span>"; 
public Customer() 
{ 
this.kBackingField = "hello world"; 
}
 
public string Name
{
    [CompilerGenerated]
    get
    {
        return this.<Name>k__BackingField;
    }
    [CompilerGenerated]
    set
    {
        this.<Name>k__BackingField = value;
    }
}
}

從生成代碼中可以看出編譯器是在實例化構造函數(shù)時,初始化屬性信息的。

自動只讀屬性默認初始化

使用方法:

public string Name1 {get;} = "hello world";

編譯器生成代碼:

public class Customer 
{
 [CompilerGenerated] 
private string kBackingField = "hello world"; 
public Customer() 
{ 
this.kBackingField = "hello world"; 
}
 
public string Name
{
    [CompilerGenerated]
    get
    {
        return this.<Name>k__BackingField;
    }
    [CompilerGenerated]
    set
    {
        this.<Name>k__BackingField = value;
    }
}
}

從生成的代碼中也可以看到編譯器是在實例化構造函數(shù)時,初始化屬性信息的。

表達式為主體的函數(shù)

使用方法:

Body Get(int x, int y) => new Body(1 + x, 2 + y);

編譯器生成代碼:

private Program.Body Get(int x, int y)
{
      return new Program.Body(1+x, 2+y);
}

從生成的代碼中可以看到簡化了單選方法的編寫,省去寫大括號的功夫。
同時也支持沒有返回值的寫法:

void OutPut(int x, int y) => Console.WriteLine("hello, world");

也支持異步函數(shù)的編寫:

async void OutPut(int x, int y) => await new Task(() => Console.WriteLine("hello world"));

表達式為主體的屬性(賦值)

使用方法:

public string Name2 => "hello world";

編譯器生成代碼如下:

public string Name2
{
     get { return "hello world"; }
}

編譯器只生成了個只讀屬性

靜態(tài)類導入

這個比較容易理解,就是一次性導入某類型的所有靜態(tài)成員,然后在后面的代碼中直接使用,比如:

using static System.Console;
class Program
{
      static void Main(string[] args}
      {
            WriteLine("hello world");
      }
}

Null 條件運算符

使用方法:

Customer cust = new Customer();
if (cust != null)
{
      string name = cust.Name;
}

等同于:

Customer cust = new Customer();
string name = cust?.Name;

可以和??組合起來使用:

if (customer?.Face()?? false)

還可以2個一起用

int? Length = customer?.Name?.Length;

這個語法糖目的是在對象使用前檢查是否為null,如果對象為空,則賦值給變量為宿舍,所以例子中需要一個可以為空的Int類型,即int?
如果對象不為空,則調(diào)用對象的成員取舍,并賦值給變量

字符串格式化

在下面的例子中,String.Format 有些不方便的地方是:必須輸入“String.Format", 使用{0}點位符,必須按順序來格式化,這點比較容易出錯:

var s = String.Format("{0} is {1} year old", p.Name, p.Age);

新的語法糖可以這么使用:

var s = $"{p.Name} is {p.Age} year old";

比較有趣的是,新格式方法還支持任何表達式的直接賦值:

var s = $"{p.Name} is {p.Age} year{(p.Age == 1 ? "" : "s")} old";

索引的初始化

使用List時,雖然可以通過下面的方式書寫,可以編譯通過,但還是會拋異常,使用方法:

var numbers = new List<string> { [7] = "seven", [9] ="nine", [13] ="thirteen"};

編譯器生成代碼:

List list = new List(); 
list[7] = "seven";
 list[9] = "nine"; 
list[13] = "thirteen";

Dictionary 可以執(zhí)行,因為二者內(nèi)部索引機制不一樣:

var numbers = new Dictionary<int, string> {[7] = "seven",[9] = "nine",[13] = "thirteen";

異常過濾器 when

使用方法:

try
{ 
throw new ArgumentException("string error");
 }
 catch (ArgumentException e) when (myfilter(e))
 { 
Console.WriteLine(e.Message);
 }
 
static bool myfilter(ArgumentException e)
 { 
return false;
 }

When語法作用是:在進入到catch之前、驗證when括號里myfilter方法返回的bool,如果返回true繼續(xù)運行,false不走catch直接拋出異常。

使用這個filter可以更好的判斷一個錯誤是繼續(xù)處理還是重新拋出去。按照以前的做法,在catch塊內(nèi)如需再次拋出去,需要重新throw出去,這時的錯誤源是捕捉后在拋的,而不是原先的,有了when語法就可以直接定位到錯誤源。

nameof表達式

有時候會需要程序中一些成員的字符串名稱,比如拋出ArgumentNullException異常的時候,想知道ArgumentNullException類型的字符串名稱,這時候就可以用nameof獲取字符

串“ArgumentNullException”。現(xiàn)在做法都是手動復制一下,但重構改名的時候容易忘記變更字符串,使用nameof就可以避免了。

string name = "";
Console.WriteLine(nameof(name));
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容