Professional C#7 and .Net Core 2.0 学习(一)

C#7中的新特性

1.数字分隔符

数字分隔符使代码更具可读性。 在声明变量时,可以将_添加到单独的数字中。 编译器只删除_。 以下代码片段在C#7中看起来更具可读性:

In C# 6
long n1 = 0x1234567890ABCDEF;
In C# 7
long n2 = 0x1234_5678_90AB_CDEF;

在C#7.2中,你也可以将_放在起始处:

In C# 7.2
long n2 = 0x_1234_5678_90AB_CDEF;

2.二进制文字

C#7为二进制文件提供了一个新的字符。 二进制文件只能包含值0和1.现在数字分隔符变得尤为重要:

In C# 7
uint binary1 = 0b1111_0000_1010_0101_1111_0000_1010_0101;

3.表达式-实体类成员

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 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.非追踪命名参数

C#支持可选参数所需的命名参数,但在任何情况下都支持可读性。 使用C#7.2,支持非尾随命名参数。 可以使用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 参数

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访问。

9.指标类型Default

使用C#7.1,定义了一个default文字,与默认运算符相比,它允许更短的语法。
默认运算符总是需要重复类型,现在不再需要了。 这对于复杂类型是实用的:

In C# 7.0
int x = default(int);
ImmutableArray arr = default(ImmutableArray);
In C# 7.1
int x = default;
ImmutableArray arr = default;

10.内部函数

在C#7之前,无法在方法中声明函数。 你可以创建一个lambda表达式并调用它,如C#6代码片段所示:

In C# 6
public void SomeFunStuff()
{
Func add = (x, y) => x + y;
int result = add(38, 4);
Console.WriteLine(result);
}
In C# 7
public void SomeFunStuff()
{
int add(int x, int y) => x + y;
int result = add(38, 4);
Console.WriteLine(result);
}

11.元组

元组允许组合不同类型的对象。 在C#7之前,元组已成为使用Tuple类的.NET Framework的一部分。 可以使用Item1,Item2,Item3访问元组的成员,等等。 在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;

推断的元组名称:

C#7.1通过自动推断元组名称来扩展元组,类似于匿名类型。 使用C#7.0,总是需要命名元组的成员。 如果元组成员应与您为其分配的属性或字段具有相同的名称,则使用C#7.1,如果未提供名称,则它与指定的成员具有相同的名称:

In C# 7.0
var t1 = (FirstName: racer.FirstName, Wins: racer.Wins);
int wins = t1.Wins;
In C# 7.1
var t1 = (racer.FirstName, racer.Wins);
int wins = t1.Wins;

12.解析构造

解构构造不是破坏者。 可以解构元组以分隔变量,例如:

In C# 7
(int n, string s) = (42, "magic");
It’s also possible to deconstruct a Person object, if a Deconstruct method is defined:
In C# 7
var p1 = new Person("Tom", "Turbo");
(string firstName, string lastName) = p1;

13.模式匹配

通过模式匹配,is运算符和switch语句增强了三种模式:const模式,类型模式和var模式。 以下代码段显示了使用is运算符的模式。 匹配的第一次检查与常量42匹配,第二次匹配检查Person对象,第三次匹配检查具有var模式的每个对象。 使用type和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子句使用相同的模式。 如果模式匹配,您还可以声明要强类型的变量。 您还可以使用何时在条件上过滤模式:

In 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;
}
}

14.抛出异常

抛出异常只能通过声明来实现; 在表达中是不可能的。 因此,当使用构造函数接收参数时,需要额外检查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));
}

15.异步主方法

在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();
}

16.ref定义

.NET Core非常注重提高性能。 为参考语义添加C#功能有助于提高性能。 在C#7之前,ref关键字可以与参数一起使用,以通过引用传递值类型。 现在,也可以将ref关键字与返回类型和局部变量一起使用。

以下代码片段声明方法GetNumber以返回对int的引用。 这样,调用者可以直接访问数组中的元素,并可以更改其内容:

In 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返回。 这样调用者不能更改返回值的内容,但仍然使用引用语义,并且可以避免返回结果时值类型的副本。 调用者接收引用但不允许更改它:

In 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

In C# 7.2
ref struct OnlyOnTheStack
{
}

 

你可能感兴趣的:(C#,C#新特性)