C# 基礎からマスターまで — 第5回
デリゲート、イベント、ラムダにアクションを渡す
本ブログ作成文は、講義を目指して製作されました。 また、作成された文章の情報も間違っている可能性がありますので、ご注意ください。
メソッドは直接呼び出すこともできますが、後で実行するアクション自体を値のように渡すこともできます。 C#のデリゲート、イベント、ラムダはこの流れを表現する。
デリゲート
int Double(int value) => value * 2;
Func<int, int> operation = Double;
int result = operation(10);
Action<string> logger = message => Console.WriteLine(message);
logger("Battle started");
Func<int, int>はintを受け取り、intを返す動作であり、Actionは戻り値がない動作です。 呼び出すコードは実際にどのメソッドが実行されるのかわからない。
イベント
public sealed class Player
{
public event Action<int>? HealthChanged;
public int Health { get; private set; } = 100;
public void TakeDamage(int amount)
{
Health = Math.Max(0, Health - amount);
HealthChanged?.Invoke(Health);
}
}
player.HealthChanged += health => healthBar.SetValue(health);
イベントは、状態を持つオブジェクトが変化を知らせ、UIやサウンドなどの他のオブジェクトが反応させます。 外部では購読と解除だけができ、イベントを勝手に呼び出せない。
購読寿命管理
void OnEnable()
{
player.HealthChanged += UpdateHealth;
}
void OnDisable()
{
player.HealthChanged -= UpdateHealth;
}
長く生きているオブジェクトのイベントに短く生きているオブジェクトが購読し続けている場合、メモリと呼び出しが残ることがあります。 登録した位置と対応する解除位置を合わせて決めなければならない。
ラムダキャプチャ
int bonus = 5;
Func<int, int> addBonus = damage => damage + bonus;
ラムダが外側のローカル変数を使用すると、その値を保持するためのオブジェクトを作成できます。 フレームごとに繰り返されるコードでキャプチャラムダを作成し続けると、不要な割り当てが発生する可能性があります。
デリゲートはアクションの種類であり、イベントは変更通知の境界を作成します。 便利であるため、すべての呼び出しをイベントに置き換えると実行順序を追跡するのが困難になるため、疎接続が必要な場所に使用する必要があります。