C# 6.0
C#已經推進到6.0了,我想一些新的語法還是有必要了解一下,
C#6.0是roslyn編譯器所支援,而roslyn是被內建在VS2015,
雖然VS2013可以透過Nuget安裝Microsoft.Net.Compilers來使用C#6.0,
但可能會有未知的相容問題,所以想要使用C#6.0新功能建議是使用VS2015。
一、自動屬性初始化 Setting default values to Auto Properties
以往自動屬性初始值無法直接指定,必須要寫在建構函式,
現在可以直接對自動屬性設定初始值
public string Name { get; set; } = "Brooke";
而C#5.0以前,自動屬性必須包含get與set,
現在C#6.0允許你可以做自動屬性唯讀初始化
public string Name { get; } = "Brooke";
二、使用 using 靜態命名類別
於C#6.0可以直接using 靜態命名類別,用法跟using命名空間很像,
只要是靜態類別,則可以使用 using static關鍵字,把類別當成命名空間來使用
using System;
using static System.Math;
namespace C_Sharp6
{
class Program
{
static void Main()
{
Console.WriteLine(Abs(-10));
Console.ReadKey();
}
}
}
三、String Interpolation
以前string.Format舊的寫法
string name = string.Format("FullName:{0},{1}", m.FirstName, m.LastName);
而使用「字串插補」功能後,新的寫法,$"{變數}"
name = $"FullName:{m.FirstName} , {m.LastName}";
也就是說String.Format( "{0}{1}" , x , y );格式會被簡化成 $"{x}{y}";
我還看過有人還會在字串插補功能再加上if判斷式,蠻令人驚奇的。
var s = $"{m.FirstName} is {m.age} year{(m.age == 1 ? "" : "s")} old";
範例如下(感謝Wesley Huang指正)
using System;
namespace C_Sharp6
{
class Program
{
static void Main()
{
Person m = new Person() { FirstName = "Lee", LastName = "Tom", age = 16 };
string name = string.Format("FullName:{0},{1}", m.FirstName, m.LastName);
name = $"FullName:{m.FirstName} , {m.LastName}";
var s = $"{m.FirstName} is {m.age} year{(m.age == 1 ? "" : "s")} old";
Console.WriteLine(name);
Console.WriteLine(s);
Console.ReadKey();
}
}
class Person
{
public string FirstName;
public string LastName;
public int age;
}
}
四、Expression-bodied function members
於 C#5.0 以前類別屬性與方法還無法使用 lambda 運算式
using System;
namespace C_Sharp6
{
class Program
{
static void Main()
{
Person m = new Person() { FirstName = "Lee", LastName = "Tom", age = 16 };
Console.WriteLine(m.FullName);
Console.ReadKey();
}
}
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int age { get; set; }
public string FullName { get { return FirstName + LastName; } }
}
}
但是現在 C#6.0 的類別屬性與方法已經可以使用 lambda 運算式了
1、屬性
using System;
namespace C_Sharp6
{
class Program
{
static void Main()
{
Person m = new Person() { FirstName = "Lee", LastName = "Tom", age = 16 };
Console.WriteLine(m.FullName);
Console.ReadKey();
}
}
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int age { get; set; }
public string FullName => $"{FirstName}{LastName}";
}
}
2、方法
using System;
namespace C_Sharp6
{
class Program
{
static void Main()
{
Person m = new Person() { FirstName = "Lee", LastName = "Tom", age = 16 };
Console.WriteLine(m.FullName());
Console.ReadKey();
}
}
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int age { get; set; }
public string FullName() => $"{FirstName}{LastName}";
}
}
五、索引初始設定式(Dictionary Initializer)
以前索引初始化都使用以下格式
var numbers = new Dictionary<int, string>()
{
{ 1, "tom"},
{ 2, "bob"},
{ 3, "tim"},
};
現在改為
var numbers1 = new Dictionary<int, string>()
{
[1] = "tom",
[2] = "bob",
[3] = "tim",
};
範例:
using System;
using System.Collections.Generic;
namespace C_Sharp6
{
class Program
{
static void Main()
{
var numbers = new Dictionary<int, string>()
{
{ 1, "tom"},
{ 2, "bob"},
{ 3, "tim"},
};
var numbers1 = new Dictionary<int, string>()
{
[1] = "tom",
[2] = "bob",
[3] = "tim",
};
Console.WriteLine(numbers1[1]);
Console.ReadKey();
}
}
}
六、Null-conditional operators「?.」、「?[]」
一般null條件判斷會這樣寫
private static int? GetFirstNameLength(Person person)
{
int? result = null;
if (person == null || person.FirstName == null)
{
return null;
}
result = person.FirstName.Length;
return result;
}
而現在可以用問號取代 == null ||,如person? ||,意思為如果person等於null時則||左邊為true;
也同義於問號取代 != null &&,如person? &&,意思為如果person不等於null時則&&左邊為true
using System;
namespace C_Sharp6
{
class Program
{
static void Main()
{
Person Person = new Person() { FirstName = "Lee", LastName = "Tom", age = 16 };
Console.WriteLine(GetFirstNameLength(Person));
Console.ReadKey();
}
private static int? GetFirstNameLength(Person person)
{
int? result = null;
//if (person == null || person.FirstName == null)
//{
// return null;
//}
result = person?.FirstName?.Length;
return result;
}
}
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int age { get; set; }
public string FullName => $"{FirstName}{LastName}";
}
}
上例GetFirstNameLength()的意思同於如果person為null時則直接回傳null,若否,
則繼續判斷FirstName是否為null,若是,則直接回傳null,若否,
則回傳FirstName的字串長度。
整個運作方式是如果左側為Null則整個運算式都是Null,
如果左側不是Null則會以點屬性表示,並成為結果。
再舉另一例子,請參考。(感謝佑翔指正)
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
//C#5.0之前
string data = "Some String";
var test = data != null ? data.Substring(0, 4) : string.Empty;
Console.WriteLine(test);
//C#6.0之後
string data2 = "Some String";
var test2 = data2?.Substring(0, 4);
Console.WriteLine(test2);
Console.ReadLine();
}
}
}
七、nameof運算子
nameof運算子功能是回傳方法或是屬性的名稱,這功能配合try catch偵錯回傳訊息會非常有幫助。
using System;
namespace C_Sharp6
{
class Program
{
static void Main()
{
Console.WriteLine(nameof(GetName));
Console.ReadKey();
}
private static string GetName()
{
return "tom";
}
}
}
以下為回傳屬性名稱
using System;
namespace ConsoleApplication1
{
class SampleClass
{
public string ID { get; set; } = "A123456789";
public string Name { get; set; } = "Brooke";
}
class Program
{
static void Main(string[] args)
{
var SampleClass = new SampleClass();
Console.WriteLine("{0} : {1}" ,nameof(SampleClass.ID),SampleClass.ID);
Console.WriteLine("{0} : {1}",nameof(SampleClass.Name),SampleClass.Name);
Console.ReadKey();
}
}
}
八、例外過濾
增加when語句來決定是否進入指定的catch區段,如下範例,當例外訊息包含了keyErrot字串時則另做處理,否則拋出例外
private static void CatchWhen()
{
try
{
var r = 0;
r = 0 / 0;
}
catch (Exception ex) when (ex.Message.Contains("keyError"))
{
Console.WriteLine("have handle exception");
}
catch (Exception ex)
{
throw;
}
}
九、例外使用非同步
於C#6.0 catch跟finally區段也能用await了,如下範例
using System;
using System.Threading.Tasks;
namespace C_Sharp6
{
class Program
{
static void Main()
{
CatchWhen();
Console.ReadKey();
}
private static async void CatchWhen()
{
try
{
var r = 0;
r = 0 / 0;
}
catch (Exception ex) when (ex.Message.Contains("keyError"))
{
Console.WriteLine("have handle exception");
await Task.Delay(500);
}
catch (Exception ex)
{
throw;
}
finally
{
await Task.Delay(500);
}
}
}
}
參考資料: