C# Expression-bodied(=>) 成员

通过表达式主体定义,可采用非常简洁的可读形式提供成员的实现。 只要任何支持的成员(如方法或属性)的逻辑包含单个表达式,就可以使用表达式主体定义。 表达式主体定义具有下列常规语法:

1
member => expression;

其中“expression”是有效的表达式。

C# 6 中引入了针对方法和只读属性的表达式主体定义支持,并在 C# 7.0 中进行了扩展。 表达式主体定义可用于下表列出的类型成员:

成员 开始提供支持的版本
方法 C# 6
只读属性 C# 6
属性 C# 7.0
构造函数 C# 7.0
终结器 C# 7.0
索引器 C# 7.0

方法

expression-bodied 方法包含单个表达式,它返回的值的类型与方法的返回类型匹配;或者,对于返回 void 的方法,其表达式则执行某些操作。 例如,替代 ToString 方法的类型通常包含单个表达式,该表达式返回当前对象的字符串表示形式。

下面的示例定义 Person 类,该类通过表达式主体定义替代 ToString。 它还定义向控制台显示名称的 DisplayName 方法。 请注意,ToString 表达式主体定义中未使用 return 关键字。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Person
{
private string fname;
private string lname;

public override string ToString() => $"{fname} {lname}".Trim();

// 等同写法
public override string ToString()
{
return $"{fname} {lname}".Trim();
}

public void DisplayName() => Console.WriteLine(ToString());

// 等同写法
public void DisplayName()
{
Console.WriteLine(ToString());
}
}

只读属性

从 C# 6 开始,可以使用表达式主体定义来实现只读属性。 为此,请使用以下语法:

1
PropertyType PropertyName => expression;

下面的示例定义 Location 类,其只读 Name 属性以表达式主体定义的形式实现,该表达式主体定义返回私有 locationName 字段值:

1
2
3
4
5
6
7
8
9
10
11
12
public class Location
{
private string locationName;

public string Name => locationName;

// 等同写法
public string Name
{
get { return locationName; }
}
}

属性

从 C# 7.0 开始,可以使用表达式主体定义来实现属性 get 和 set 访问器。 下面的示例演示其实现方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Location
{
private string locationName;

public string Name
{
get => locationName;
set => locationName = value;
}

// 等同写法
public string Name
{
get { return locationName; }
set { locationName = value; }
}
}

构造函数

构造函数的表达式主体定义通常包含单个赋值表达式或一个方法调用,该方法调用可处理构造函数的参数,也可初始化实例状态。

以下示例定义 Location 类,其构造函数具有一个名为“name”的字符串参数。 表达式主体定义向 Name 属性分配参数。

1
2
3
4
5
6
7
8
9
10
11
12
public class Location
{
private string locationName;

public Location(string name) => Name = name;

// 等同写法
public Location(string name)
{
Name = name;
}
}

终结器

终结器的表达式主体定义通常包含清理语句,例如释放非托管资源的语句。

下面的示例定义了一个终结器,该终结器使用表达式主体定义来指示已调用该终结器。

1
2
3
4
5
6
7
8
9
10
11
12
public class Destroyer
{
public override string ToString() => GetType().Name;

~Destroyer() => Console.WriteLine($"The {ToString()} finalizer is executing.");

// 等同写法
~Destroyer()
{
Console.WriteLine($"The {ToString()} finalizer is executing.");
}
}

索引器

与使用属性一样,如果 get 访问器包含返回值的单个表达式或 set 访问器执行简单的赋值,则索引器 get 和 set 访问器包含表达式主体定义。

下面的示例定义名为 Sports 的类,其中包含一个内部 String 数组,该数组包含大量体育运动的名称。 索引器的 get 和 set 访问器都以表达式主体定义的形式实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using System;
using System.Collections.Generic;

public class Sports
{
private string[] types = { "Baseball", "Basketball", "Football",
"Hockey", "Soccer", "Tennis",
"Volleyball" };

public string this[int i]
{
get => types[i];
set => types[i] = value;
}

// 等同写法
public string this[int i]
{
get { return types[i]; }
set { types[i] = value; }
}
}

本文参考:https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/statements-expressions-operators/expression-bodied-members