通过表达式主体定义,可通过简洁可读的形式提供成员的实现。 只要任何支持的成员(如方法或属性)的逻辑包含单个表达式,就可以使用表达式主体定义。 表达式主体定义具有下列常规语法:
member => expression;
其中“expression”是有效的表达式。
表达式主体定义可用于以下类型成员:
方法
expression-bodied 方法包含单个表达式,它返回的值的类型与方法的返回类型匹配;或者,对于返回 void
的方法,其表达式则执行某些操作。 例如,替代 ToString 方法的类型通常包含单个表达式,该表达式返回当前对象的字符串表示形式。
下面的示例定义 Person
类,该类通过表达式主体定义替代 ToString。 它还定义向控制台显示名称的 DisplayName
方法。 此外,它还包括多个采用参数的方法,演示表达式体成员如何使用方法参数。 关键字 return
不在任何表达式正文定义中使用。
using System;
namespace ExpressionBodiedMembers;
public class Person
{
public Person(string firstName, string lastName)
{
fname = firstName;
lname = lastName;
}
private string fname;
private string lname;
public override string ToString() => $"{fname} {lname}".Trim();
public void DisplayName() => Console.WriteLine(ToString());
// Expression-bodied methods with parameters
public string GetFullName(string title) => $"{title} {fname} {lname}";
public int CalculateAge(int birthYear) => DateTime.Now.Year - birthYear;
public bool IsOlderThan(int age) => CalculateAge(1990) > age;
public string FormatName(string format) => format.Replace("{first}", fname).Replace("{last}", lname);
}
class Example
{
public static void Main()
{
Person p = new Person("Mandy", "Dejesus");
Console.WriteLine(p);
p.DisplayName();
// Examples with parameters
Console.WriteLine(p.GetFullName("Dr."));
Console.WriteLine($"Age: {p.CalculateAge(1990)}");
Console.WriteLine($"Is older than 25: {p.IsOlderThan(25)}");
Console.WriteLine(p.FormatName("Last: {last}, First: {first}"));
}
}
有关详细信息,请参阅方法(C# 编程指南)。
只读属性
可使用表达式主体定义来实现只读属性。 为此,请使用以下语法:
PropertyType PropertyName => expression;
下面的示例定义 Location
类,其只读 Name
属性以表达式主体定义的形式实现,该表达式主体定义返回私有 locationName
字段值:
public class Location
{
private string locationName;
public Location(string name)
{
locationName = name;
}
public string Name => locationName;
}
有关属性的详细信息,请参阅属性(C# 编程指南)。
属性
可使用表达式主体定义来实现属性 get
和 set
访问器。 下面的示例演示其实现方法:
public class Location
{
private string locationName;
public Location(string name) => Name = name;
public string Name
{
get => locationName;
set => locationName = value;
}
}
// Example with multiple parameters
public class Point
{
public double X { get; }
public double Y { get; }
// Constructor with multiple parameters
public Point(double x, double y) => (X, Y) = (x, y);
// Constructor with single parameter (creates point at origin on axis)
public Point(double coordinate) => (X, Y) = (coordinate, 0);
}
有关属性的详细信息,请参阅属性(C# 编程指南)。
事件
同样,可以使用 expression-bodied 方法编写事件 add
和 remove
访问器:
public class ChangedEventArgs : EventArgs
{
public required int NewValue { get; init; }
}
public class ObservableNum(int _value)
{
public event EventHandler<ChangedEventArgs> ChangedGeneric = default!;
public event EventHandler Changed
{
// Note that, while this is syntactically valid, it won't work as expected because it's creating a new delegate object with each call.
add => ChangedGeneric += (sender, args) => value(sender, args);
remove => ChangedGeneric -= (sender, args) => value(sender, args);
}
public int Value
{
get => _value;
set => ChangedGeneric?.Invoke(this, new() { NewValue = (_value = value) });
}
}
有关事件的详细信息,请参阅事件(C# 编程指南)。
构造函数
构造函数的表达式主体定义通常包含单个赋值表达式或一个方法调用,该方法调用可处理构造函数的参数,也可初始化实例状态。
以下示例定义 Location
类,其构造函数具有一个名为“name”的字符串参数。 表达式主体定义向 Name
属性分配参数。 该示例还演示了一个 Point
包含构造函数的类,这些构造函数采用多个参数,演示表达式体构造函数如何使用不同的参数组合。
public class Location
{
private string locationName;
public Location(string name) => Name = name;
public string Name
{
get => locationName;
set => locationName = value;
}
}
// Example with multiple parameters
public class Point
{
public double X { get; }
public double Y { get; }
// Constructor with multiple parameters
public Point(double x, double y) => (X, Y) = (x, y);
// Constructor with single parameter (creates point at origin on axis)
public Point(double coordinate) => (X, Y) = (coordinate, 0);
}
有关详细信息,请参阅构造函数(C# 编程指南)。
终结器
终结器的表达式主体定义通常包含清理语句,例如释放非托管资源的语句。
下面的示例定义了一个终结器,该终结器使用表达式主体定义来指示已调用该终结器。
public class Destroyer
{
public override string ToString() => GetType().Name;
~Destroyer() => Console.WriteLine($"The {ToString()} finalizer is executing.");
}
有关详细信息,请参阅终结器(C# 编程指南)。
索引器
与使用属性一样,如果 get
访问器包含返回值的单个表达式或 set
访问器执行简单的赋值,则索引器 get
和 set
访问器包含表达式主体定义。
下面的示例定义名为 Sports
的类,其中包含一个内部 String 数组,该数组包含一些体育运动的名称。 索引器的 get
和 set
访问器都以表达式主体定义的形式实现。
using System;
using System.Collections.Generic;
namespace SportsExample;
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;
}
}
有关详细信息,请参阅索引器(C# 编程指南)。