
C#言語の基本:デリゲートの使い方
以前、インターン生からプロジェクトのサポート依頼を受けました。その時、コードの編成方法を確認する機会があり、あることに気づきました。C#には、非常に優れた手法があるのに、使用されていないことです。それは、コードの編成方法の補助知識であり、クラスの結合度を下げる同時に、他のメンバーのコードも理解やすくなります。
その場で、インターン生たちにこの技術を教えましたが、改めて記事で詳しく説明したいと思います。この技術への理解を深め、今後のプロジェクトに お役に立てれば幸いです。
本記事では、C#のデリゲートの使い方について解説させていただきます。
1. ケース
簡単な例をあげます。プレイヤーには、ジャンプの機能があるとします。PlayerControllerのクラス内には、以下のようにJump()のメソッドがあるでしょう。
やめて!そのようなやり方をしないで!この状態だと、PlayerControllerクラスは、PlayerSoundSfxクラス、PlayerEffectSpawnerクラス、PlayerJumpCounterクラスに対して、依存関係が強いです。
一つのプログラムにおいて、一つのクラスがたくさんのクラスに依存する場合、メンテナンスが難しくなります。例えば、プレイヤーがジャンプするときのエフェクトを廃止することになった場合、PlayerEffectSpawnerクラスの削除に加えて、PlayerControllerクラスの修正も必要になります。または、プロジェクトで複数人で作業をする場合、Aさんがプレイヤーがジャンプするときのサウンド再生を担当し、Bさんがジャンプするときのエフェクト再生を担当するとします。二人ともPlayerControllerクラスのJump 関数を修正する必要があるため、gitでコード統合を行うと、コンフリクトを発生させる可能性があります。
2. ソリューション
では、対策として何があるのでしょうか。
PlayerControllerでは、プレイヤーを操作するという一つだけの機能にします。 プレイヤーがジャンプすると、その旨を通知するイベントを作成します。このとき、PlayerControllerは独立的にジャンプ機能を実行し、他の機能(エフェクト再生・サウンド再生・ジャンプ回数カウントなど)に配慮する必要がありません。
この場合は、デリゲートを使います。
デリゲートは、C#の関数参照方法です。デリゲートを呼び出すことで、デリゲートを通して参照される関数を呼び出すことができます。(ここでのデリゲートの呼び出しはInvokeという)
OnPlayerJumpDelegateという名前のデリゲートを定義します。戻り値のデータ型はvoidです。デリゲートは関数の代表となるので、戻り値のデータ型の設定が必要です。