【Professional C# 7 and .NET Core 2.0】C#7的新特性
1 数字分隔符
数字分隔符使代码更具可读性。在声明变量时可以给单独的数字添加_。编译器只是删除_。
//C# 6 long n1 = 0x1234567890ABCDEF; //C# 7 long n2 = 0x_1234_5678_90AB_CDEF;
在C# 7.2中,也可以把“_”放在开头。
//C# 7.2 long n2 = 0x_1234_5678_90AB_CDEF;
数字分隔符在第2章介绍。
2 二进制字面值
C# 7为二进制提供了一个新的字面值。二进制的值只能是0和1。
//C# 7 uint binary1 = 0b1111_0000_1010_0101_1111_0000_1010_0101;
二进制字面值在第2章介绍。
3 表达式体的成员
在C# 7中,表达式体可以与构造函数、析构函数、本地函数、属性访问器等一起使用。
//C# 6 private string _firstName; public string FirstName { get { return _firstName; } set { Set(ref _firstName, value); } } //C# 7 private string _firstName; public string FirstName { get => _firstName; set => Set(ref _firstName, value); }
表达式体的成员在第3章介绍。
4 out 变量
在C# 7之前,out变量必须在使用之前声明。而在C# 7中,代码减少了一行,因为变量可以在使用时声明
//C# 6 string n = "42"; int result; if (string.TryParse(n, out result) { Console.WriteLine($"Converting to a number was successful: {result}"); } //C# 7 string n = "42"; if (string.TryParse(n, out var result) { Console.WriteLine($"Converting to a number was successful: {result}"); }
这个特性在第3章介绍。
5 不拖尾的命名参数
C# 7.2支持不拖尾的命名参数。参数名可以添加到C# 7.2的任何参数中
//C# 7.0 if (Enum.TryParse(weekdayRecommendation.Entity, ignoreCase: true, result: out DayOfWeek weekday)) { reservation.Weekday = weekday; } //C# 7.2 if (Enum.TryParse(weekdayRecommendation.Entity, ignoreCase: true, out DayOfWeek weekday)) { reservation.Weekday = weekday; }
命名参数在第3章介绍。
6 只读结构
在C# 7.2中,可以使用readonly修饰符声明结构体,因此编译器可以验证结构体没有更改。编译器也可以使用此保证,不复制作为参数传递给它的结构,但把它传递为引用
//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); }
只读结构在第3章介绍。
7 in参数
C# 7.2还允许给参数使用in修饰符。这就保证了所传递的值类型不会更改,并可以通过引用来传递,以避免复制
//C# 7.2 static void CantChange(in AStruct s) { // s can't change }
ref、in 和 out 修饰符在第3章介绍。
8 Private Protected
C# 7.2添加了一个新的访问修饰符private protected。如果某成员用于同一程序集中的类型,或派生自类的另一个程序集的类型,那么访问修饰符protected internal允许访问它。使用private protected时,上述两个条件使用AND而不是OR——只有当类派生自基类,且位于同一程序集中时,才允许访问。
访问修饰符在第4章中介绍。
9 目标类型的default
在C# 7.1中,定义了default字面值,与default操作符相比,它允许使用更短的语法。default操作符总是需要类型的重复,现在不再需要了。
//C# 7.0 int x = default(int); ImmutableArray<int> arr = default(ImmutableArray<int>); //C# 7.1 int x = default; ImmutableArray<int> arr = default;
default 字面值在第5章介绍。
10 本地函数
在C# 7之前,不可能在方法中声明函数。而可以创建一个lambda表达式并调用它
//C# 6 public void SomeFunStuff() { Func<int, int, int> add = (x, y) => x + y; int result = add(38, 4); Console.WriteLine(result); }
在C# 7中,可以在方法中声明一个本地函数。本地函数只能在方法的作用域内访问
//C# 7 public void SomeFunStuff() { int add(int x, int y) => x + y; int result = add(38, 4); Console.WriteLine(result); }
本地函数在第13章解释。本书的几个章节介绍了它的不同用途。
11 元组
//C# 6 var t1 = Tuple.Create(42, "astring"); int i1 = t1.Item1; string s1 = t1.Item2; //C# 7 var t1 = (n: 42, s: "magic"); int i1 = t1.n; string s1 = t1.s;
元组的所有更改都包含在第13章中。
12 推断的元组名
C# 7.1通过自动推断元组名称来扩展元组,类似于匿名类型。在C# 7.0中,元组的成员总是需要命名。如果元组成员的名称应该与分配给它的属性或字段相同,那么在C# 7.1中,如果不提供名称,它就与分配给它的成员的名称相同
//C# 7.0 var t1 = (FirstName: racer.FirstName, Wins: racer.Wins); int wins = t1.Wins; //C# 7.1 var t1 = (racer.FirstName, racer.Wins); int wins = t1.Wins;
13 拆解
元组可以拆解成独立的变量
//C# 7 (int n, string s) = (42, "magic"); //C# 7 var p1 = new Person("Tom", "Turbo"); (string firstName, string lastName) = p1;
拆解在第13章介绍。
14 模式匹配
使用模式匹配,is操作符和switch语句增强为三种模式:const模式、类型模式和var模式。
//C# 7 public void PatternMatchingWithIsOperator(object o) { if (o is 42) { } if (o is Person p) { } if (o is var v1) { } }
通过switch语句,可以对case子句使用相同的模式。如果模式匹配,则可以将变量声明为强类型。也可以在以下条件下使用when过滤模式
//C# 7 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; } }
模式匹配在第13章中介绍。
15 Throw 表达式
在C# 7中,可以在表达式中抛出异常,因此可以使用合并操作符在左侧为null时抛出ArgumentNullException异常。
//C# 6 private readonly IBooksService _booksService; public BookController(BooksService booksService) { if (booksService == null) { throw new ArgumentNullException(nameof(b)); } _booksService = booksService; } //C# 7 private readonly IBooksService _booksService; public BookController(BooksService booksService) { _booksService = booksService ?? throw new ArgumentNullException(nameof(b)); }
Throw表达式在第14章中介绍。
16 异步Main()方法
在C# 7.1之前,Main()方法总是需要声明为类型void。在C# 7.1中,Main()方法也可以是Task类型,使用async和await关键字
//C# 7.0 static void Main() { SomeMethodAsync().Wait(); } //C# 7.1 async static Task Main() { await SomeMethodAsync(); }
异步编程在第15章介绍。
17 引用语义
在C# 7之前,ref关键字可以与参数一起使用,通过引用传递值类型。现在也可以对返回类型和本地变量使用ref关键字。
//C# 7.0 int[] _numbers = { 3, 7, 11, 15, 21 }; public ref int GetNumber(int index) { return ref _numbers[index]; }
在C# 7.2中,readonly修饰符可以添加到ref返回值上。这样,调用者不能更改返回值的内容,但仍然使用引用语义,并可以避免在返回结果时复制值类型。调用方收到引用,但不允许更改引用
//C# 7.2 int[] _numbers = { 3, 7, 11, 15, 21 }; public ref readonly int GetNumber(int index) { return ref _numbers[index]; }
在C# 7.2之前,C#可以创建引用类型(类)和值类型(结构)。然而,装箱时,结构体也可以存储在堆中。在C# 7.2中,可以声明一个类型ref struct,该类型只允许放在堆栈上
//C# 7.2 ref struct OnlyOnTheStack { }
引用的新特性在第17章中介绍。
浙公网安备 33010602011771号