Expression-bodied 成员(C# 编程指南)

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

member => expression;

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

表达式主体定义可用于以下类型成员:

方法

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

下面的示例定义 Person 类,该类通过表达式主体定义替代 ToString。 它还定义向控制台显示名称的 DisplayName 方法。 ToString 表达式主体定义中未使用 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());
}

class Example
{
   static void Main()
   {
      Person p = new Person("Mandy", "Dejesus");
      Console.WriteLine(p);
      p.DisplayName();
   }
}

有关详细信息,请参阅方法(C# 编程指南)

只读属性

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

PropertyType PropertyName => expression;

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

public class Location
{
   private string locationName;

   public Location(string name)
   {
      locationName = name;
   }

   public string Name => locationName;
}

有关属性的详细信息,请参阅属性(C# 编程指南)

属性

可使用表达式主体定义来实现属性 getset 访问器。 下面的示例演示其实现方法:

public class Location
{
   private string locationName;

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

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

有关属性的详细信息,请参阅属性(C# 编程指南)

事件

同样,可以使用 expression-bodied 方法编写事件 addremove 访问器:

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 属性分配参数。

public class Location
{
   private string locationName;

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

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

有关详细信息,请参阅构造函数(C# 编程指南)

终结器

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

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

public class Destroyer
{
   public override string ToString() => GetType().Name;

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

有关详细信息,请参阅终结器(C# 编程指南)

索引器

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

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

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# 编程指南)

另请参阅