【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章中介绍。

posted @ 2020-01-11 17:39  FH1004322  阅读(429)  评论(0)    收藏  举报