式形式のメンバー (C# プログラミング ガイド)
式本体の定義を使用すると、メンバーの実装が簡潔でわかりやすい形式になります。 サポートされる任意のメンバー (メソッドやプロパティなど) に関するロジックが単一の式で構成される場合は、常に式本体の定義を使用できます。 式本体の定義には、次の一般的な構文があります。
member => expression;
この expression には有効な式を指定します。
式本体の定義は、次の型メンバーで使用できます。
メソッド
式形式のメソッドは、型がメソッドの戻り値の型と一致する値を返す単一の式、または、void
を返すメソッドの場合は何らかの処理を実行する単一の式で構成されます。 たとえば、一般的に、ToString メソッドをオーバーライドする型には、現在のオブジェクトの文字列形式を返す単一の式が含まれています。
次の例では、式本体の定義を使用して ToString メソッドをオーバーライドする Person
クラスを定義します。 また、名前をコンソールに表示する 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;
次の例では、プライベート locationName
フィールドの値を返す式本体の定義として読み取り専用の Name
プロパティを実装する Location
クラスを定義します。
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;
}
}
プロパティの詳細については、「プロパティ (C# プログラミング ガイド)」を参照してください。
Events
同様に、イベント 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# プログラミング ガイド)」を参照してください。
コンストラクター
一般的に、コンストラクターの式本体の定義は、コンストラクターの引数を処理したり、インスタンスの状態を初期化したりする単一の代入式またはメソッド呼び出しから構成されます。
次の例では、コンストラクターに name という名前の文字列パラメーターが 1 つある Location
クラスが定義されています。 式の本体の定義により 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
アクセサーがシンプルな代入を実行する場合、インデクサーの 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# プログラミング ガイド)」を参照してください。
こちらもご覧ください
.NET