1.數字分隔符(Digit Separators ) 數字分隔符使代碼更具可讀性。在聲明變數時,可以將_添加到單獨的數字中。編譯器只刪除_。以下代碼片段在C#7中看起來更具可讀性: In C# 6 In C# 7 In C# 7.2 2.二進位(Binary Literals ) C#7為二進位文件 ...
1.數字分隔符(Digit Separators )
數字分隔符使代碼更具可讀性。在聲明變數時,可以將_添加到單獨的數字中。編譯器只刪除_。以下代碼片段在C#7中看起來更具可讀性:
In C# 6
long n1 = 0x1234567890ABCDEF;
In C# 7
long n2 = 0x1234_5678_90AB_CDEF;
In C# 7.2
long n2 = 0x_1234_5678_90AB_CDEF;
2.二進位(Binary Literals )
C#7為二進位文件提供了一個新的文字。二進位文件只能包含va 0和1。現在,數字分隔符變得尤為重要
In C# 7
uint binary1 = 0b1111_0000_1010_0101_1111_0000_1010_0101;
3.Expression-bodied 函數成員(Expression-Bodied Members )
C#6允許表達式方法和屬性。使用C#7,表達式主體可以與構造函數,析構函數,本地函數,屬性訪問器等一起使用。在這裡,您可以看到C#6和C#7之間的屬性訪問器的區別:
In C# 6
private string _firstName; public string FirstName { get { return _firstName; } set { Set(ref _firstName, value); } }
In C# 7
private string _firstName; public string FirstName { get => _firstName; set => Set(ref _firstName, value); }
4.Out 變數(Out Var)
在C#7之前,必須在使用之前聲明out變數。使用C#7,代碼減少了一行,因為變數可以聲明
使用:
In C# 6
string n = "42"; int result; if (string.TryParse(n, out result) { Console.WriteLine($"Converting to a number was successful:{result}"); }
In C# 7
string n = "42"; if (string.TryParse(n, out var result) { Console.WriteLine($"Converting to a number was successful:{result}"); }
5.非尾隨命名參數(Non-Trailing Named Arguments )
使用C#7.2,支持非尾隨命名參數。有關詳細信息,請參閱命名參數和可選參數。
In C# 7.0
if (Enum.TryParse(weekdayRecommendation.Entity, ignoreCase:true,result: out DayOfWeek weekday)) { reservation.Weekday = weekday; }
In C# 7.2
if (Enum.TryParse(weekdayRecommendation.Entity, ignoreCase:true,out DayOfWeek weekday)) { reservation.Weekday = weekday; }
6.只讀結構(Readonly Struct )
結構應該是只讀的(有一些例外)。使用C#7.2,可以使用readonly修飾符聲明結構,因此編譯器會驗證結構是否未更改。編譯器也可以使用此保證不複製將其作為參數傳遞的結構,而是將其作為引用傳遞:
In C# 7.2
public readonly struct Dimensions { public double Length { get; } public double Width { get; } public Dimensions(double length, double width) { Length = length; Width = width; } public double Diagonal => Math.Sqrt(Length * Length + Width * Width); }
7.In 修飾參數(In Parameters )
C#7.2還允許帶有參數的in修飾符。這可以保證傳遞的值類型不會改變,它可以通過引用傳遞以避免副本:
In C# 7.2
static void CantChange(in AStruct s) { // s can't change }
8.private protected 訪問修飾符
C#7.2添加了一個新的訪問修飾符:private protected。訪問修飾符protected internal允許訪問該成員(如果已使用)來自同一程式集中的類型,或來自派生自該類的另一個程式集中的類型。對於private protected,如果類派生自基類並且在同一個程式集中,則只允許使用AND而不是OR訪問。
使用C#7.1,定義了一個預設文字,與預設運算符相比,它允許更短的語法。預設運算符總是需要重覆類型,現在不再需要了。
In C# 7.0
int x = default(int); ImmutableArray<int> arr = default(ImmutableArray<int>);
In C# 7.1
int x = default; ImmutableArray<int> arr = default;
10.本地函數(Local Functions )
在C#7之前,無法在方法中聲明函數。你可以創建一個lambda表達式並調用它,如C#6代碼片段所示:
In C# 6
public void SomeFunStuff() { Func<int, int, int> add = (x, y) => x + y; int result = add(38, 4); Console.WriteLine(result); }
使用C#7,可以在方法中聲明本地函數。只能在方法範圍內訪問本地函數:
In C# 7
public void SomeFunStuff() { int add(int x, int y) => x + y; int result = add(38, 4); Console.WriteLine(result); }
11.元組(Tuples )
低於 C# 7.0 的版本中也提供元組,但它們效率低下且不具有語言支持。 這意味著元組元素只能作為 Item1
和 Item2
等引用。C# 7.0 引入了對元組的語言支持,可利用更有效的新元組類型向元組欄位賦予語義名稱。在C#7中,元組是語言的一部分,你可以定義成員的名字:
in C# 6
var t1 = Tuple.Create(42, "astring"); int i1 = t1.Item1; string s1 = t1.Item2;
In C# 7
var t1 = (n: 42, s: "magic"); int i1 = t1.n; string s1 = t1.s;
12.推斷元組元素名稱(Inferred Tuple Names )
此功能是對 C# 7.0 中引入的元組功能一次小型增強。 在初始化元組時,許多時候,賦值操作右側的變數名與用於元組元素的名稱相同,元組元素的名稱可通過在 C# 7.1 中初始化元組時使用的變數進行推斷:
In C# 7.0
int count = 5; string label = "Colors used in the map"; var pair = (count: count, label: label);
In C# 7.1
int count = 5; string label = "Colors used in the map"; var pair = (count, label); // element names are "count" and "label"
13.析構元組(Deconstructors )
在某些時候,你可能想要解包從方法返回的元組的成員。 可通過為元組中的每個值聲明單獨的變數來實現此目的。 這種解包操作稱為析構元組
In C# 7
var p1 = new Person("Tom", "Turbo"); (string firstName, string lastName) = p1;
14.模式匹配(Pattern Matching )
通過模式匹配,is運算符和switch語句增強了三種模式:const模式,類型模式和var模式。以下代碼段顯示
使用is運算符的模式。匹配的第一次檢查與常量42匹配,第二次匹配檢查Person對象,第三次匹配檢查具有var模式的每個對象。使用類型和var模式,可以為強類型訪問聲明變數:
In C# 7
public void PatternMatchingWithIsOperator(object o) { if (o is 42) { } if (o is Person p) { } if (o is var v1) { } }
使用switch語句,可以對case子句使用相同的模式。如果模式匹配,您還可以聲明要強類型的變數。您還可以使用何時在條件上過濾模式:
public void PatternMatchingWithSwitchStatement(object o) { swtich (o) { case 42: break; case Person p when p.FirstName == "Katharina": break; case Person p: break; case var v: break; } }
註:使用 when
關鍵字來指定模式的其他規則。
15.Throw表達式(Throw Expressions )
拋出異常只能通過聲明來實現;在表達中是不可能的。因此,當使用構造函數接收參數時,需要額外檢查null以拋出ArgumentNullException。使用C#7,可以在表達式中拋出異常,因此當左側為空時,可以使用合併運算符拋出ArgumentNullException
In C# 6
private readonly IBooksService _booksService; public BookController(BooksService booksService) { if (booksService == null) { throw new ArgumentNullException(nameof(b)); } _booksService = booksService; }
In C# 7
private readonly IBooksService _booksService; public BookController(BooksService booksService) { _booksService = booksService ?? throw new ArgumentNullException(nameof(b)); }
16.非同步Main方法
在C#7.1之前,Main方法總是需要聲明為void類型。用C#7。1,Main方法也可以是Task類型,並使用async和await關鍵字:
In C# 7.0
static void Main() { SomeMethodAsync().Wait(); }
In C# 7.1
async static Task Main() { await SomeMethodAsync(); }
17.條件Ref表達式
以下代碼片段聲明方法GetNumber以返回對int的引用。這條路,調用者可以直接訪問數組中的元素,並可以更改其內容:
In C# 7.0
int[] _numbers = { 3, 7, 11, 15, 21 }; public ref int GetNumber(int index) { return ref _numbers[index]; }
In C# 7.2
變數 r
是對 arr
或 otherArr
中第一個值的引用。
ref var r = ref (arr != null ? ref arr[0] : ref otherArr[0]);
擴展:
1.使用C#7.2,可以將readonly修飾符添加到ref返回。調用者接收引用但不允許更改它:
In C# 7.2
int[] _numbers = { 3, 7, 11, 15, 21 }; public ref readonly int GetNumber(int index) { return ref _numbers[index]; }
2.ref Struct (在C#7.2之前,C#可以創建引用類型(類)和值類型(結構)。但是,當發生裝箱時,結構也可以存儲在堆上。用C#7.2,可以聲明只允許在堆棧上使用的類型:ref struct)
In C# 7.2
ref struct OnlyOnTheStack { }
C# 更多語法糖請參閱微軟官方文檔.https://docs.microsoft.com/zh-cn/dotnet/csharp/whats-new/index