微軟在Visual Studio 2015中更新C#語言到6.0,添加了很多很好的特性,以使C#語言繼續跻身於最優秀語言之行列。下面通過一個例子快速感受一下C# 6.0的新特性,以下程序在VS2015預覽版中測試通過,正式版可能還要添加新特性。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Console; namespace CSharp6Research { //分數 public class Fraction { public int A { get; set; } public int B { get; set; } = 1; public string Separator { get; } = "/"; public string SeparatorSpaces { get; } = string.Empty; public double Value => (double)A / B; public int this[int index] => index == 0 ? A : B; public int this[string index] => index == "A" ? A : B; public override string ToString() => "\{A}\{SeparatorSpaces}\{Separator}\{SeparatorSpaces}\{B}"; public void Print() => WriteLine(ToString()); public Fraction() { } public Fraction(int a, int b) { A = a; B = b; } public Fraction(int a, int b, string separatorSpaces) : this(a, b) { SeparatorSpaces = separatorSpaces; if (string.IsNullOrEmpty(separatorSpaces)) { throw new ArgumentNullException(nameof(separatorSpaces)); } } public static readonly Dictionary<string, Fraction> CommonFractions = new Dictionary<string, Fraction> { ["zero"] = new Fraction(), ["one"] = new Fraction(1, 1), ["half"] = new Fraction(1, 2), ["quarter"] = new Fraction(1, 4), ["infinity"] = new Fraction(1, 0), }; } public struct FractionStruct { public int A { get; } public int B { get; } public FractionStruct(int a, int b) { A = a; B = b; } public FractionStruct() : this(0, 1) { } public override string ToString() => "\{A}/\{B}"; } class Program { static void Main(string[] args) { foreach (var f in Fraction.CommonFractions) { WriteLine("\{f.Key} : \{f.Value.Value}"); } var fraction = new Fraction(1, 3, " "); fraction.Print(); try { fraction = new Fraction(1, 2, null); } catch (ArgumentNullException e) if (e.ParamName == "separatorSpaces") { WriteLine("separatorSpaces can not be null"); } Fraction v; Fraction.CommonFractions.TryGetValue("harf", out v); v?.Print(); var a = v?.A; WriteLine(a == null); var b = v?["B"]; WriteLine(b == null); WriteLine(v?.ToString() == null); WriteLine(new FractionStruct().ToString()); WriteLine(default(FractionStruct).ToString()); } } }
運行結果如下,
zero : 0 one : 1 half : 0.5 quarter : 0.25 infinity : ∞ 1 / 3 separatorSpaces can not be null True True True 0/1 0/0
1. Auto-property initializers 自動屬性初始化器
public int B { get ; set ; } = 1;
可以直接給自動屬性賦值了,不需要寫在構造函數中了。
2. Getter-only auto-properties 只讀自動屬性
public string SeparatorSpaces { get; } = string.Empty;
只讀自動屬性可以直接初始化,或者在構造函數中初始化。
3. Expression-bodied members 表達式體成員
public double Value => (double)A / B;
public int this[int index] => index == 0 ? A : B;
public void Print() => WriteLine(ToString());
只讀屬性,只讀索引器和方法都可以使用Lambda表達式作為Body。
4. String interpolation 字符串嵌入值
"\{A}\{SeparatorSpaces}\{Separator}\{SeparatorSpaces}\{B}";
反斜槓後的大括號中的表達式會在運行時計算值,並嵌入到字符串中。和Swift中很像,Swift中是反斜槓加小括號,C#是反斜槓加大括號。
5. nameof operator nameof 運算符
throw new ArgumentNullException(nameof(separatorSpaces));
nameof會返回變量,參數或成員名。
這個很有用,原來寫WPF中的ViewModel層的屬性變化通知時,需要寫字符串,或者使用MvvmLight等庫中的幫助方法,可以直接傳入屬性,但由於是在運行時解析,會有少許性能損失。現在好了,使用nameof運算符,既能保證重構安全和可讀性,又能保證性能。
6. Dictionary initializer 字典初始化器
new Dictionary< string, Fraction>
{
["zero"] = new Fraction (),
["one"] = new Fraction (1, 1),
["half"] = new Fraction (1, 2),
["quarter"] = new Fraction (1, 4),
[ "infinity"] = new Fraction (1, 0),
};
現在字典可以用一種可讀性更好的方法進行初始化,方括號包圍的Key等於Value。
7. Parameterless struct ctors 無參數的結構體構造函數
public FractionStruct( int a, int b) { A = a; B = b; }
public FractionStruct() : this(0, 1) { }
結構體可以提供自定義的無參數構造函數了。
new FractionStruct()
default(FractionStruct)
new是調用無參數構造函數。
default是不調用無參數構造函數。
8. Exception filters 異常過濾器
catch (ArgumentNullException e) if (e.ParamName == "separatorSpaces")
{
WriteLine("separatorSpaces can not be null");
}
設置進入catch塊的條件。
9. Null propagation 空傳播
v?.A
v?["B"]
v?.ToString()
對象為null時不調用屬性,索引器,方法等,表達式返回null,和Swift中的用法相似。
10. Using static members using靜態導入
using System.Console ;
WriteLine("separatorSpaces can not be null" );
在using中可以指定一個靜態類,然後可以在隨後的代碼中直接使用該類的靜態方法,和Java中的用法相似。
11. Await in catch/finally catch和finally塊中的await
例子如下,
Resource res = null;
try
{
res = await Resource.OpenAsync(…); // You could do this.
…
}
catch (ResourceException e)
{
await Resource.LogAsync(res, e); // Now you can do this …
}
finally
{
if (res != null) await res.CloseAsync(); // … and this.
}