[Effective C#] 項目21 デリゲートを使用してコールバックを実現する

本日の Effective C# は「項目21 デリゲートを使用してコールバックを実現する」です。

コールバックは激しく便利です。C# はデリゲートというのがあるので、これを利用してコールバックが書けます。Java だとこれがないのでインターフェイスを利用する必要があります。

特定のクラス間でデータをやり取りする必要があるけども、互いのインターフェイスを使用するほどには密に連携させたくない場合、デリゲートは最善の選択肢だといえます。

そうなんですよね。ちょろっとしたことなら、インターフェイスよりデリゲートの方が便利なんですよね。

マルチキャストデリゲートは複数のメソッドが登録されたデリゲートで、1 回の呼び出しで登録されたメソッドを呼び出すことができます。ただし注意すべき点が 2 つあります。一つは例外に対して安全ではないこと、もうひとつはマルチキャストデリゲートの返り値は最後に実行されたメソッドの返り値になるということです。

例外の件はともかくとして、返り値が一つしか、しかも最後のメソッドのもののみってのは大問題な気がします。

private void Execute(Func<bool> functions)
{
    Debug.WriteLine(functions());
}

というコードがあったとき、(本来なら、引数の functions は null check が必要だと思う)

Func<bool> functions = delegate { return false; };
functions += delegate { return true; };
Execute(functions);

というコードは "True" と表示されます。これはさすがに想定外だと思います。

ですので、

private void Execute(Func<bool> functions)
{
    bool result = false;
    foreach (Func<bool> func in functions.GetInvocationList())
    {
        result &= func();
    }
    Debug.WriteLine(result);
}

のように書く必要があるんだそうな。

というか、お恥ずかしいことに、この本を読むまでマルチキャストデリゲートの存在を失念していました。ですので、引数として受け取ったデリゲートがマルチキャストかどうか考えていないわけで、結構怖いですよね。

多分、イベントのためだと思うんですが、マルチキャストデリゲートって存在しない方がいい気がするんですよね。マルチキャストデリゲートが困る場合でも、それを止めることができないですし。

マルチキャストというか、デリゲートが複数必要な場合は、

public void Execute(IEnumerable<Func<bool>> functions)

でいいじゃん! みたいな。見分けつくし、呼び出し順序も理解しやすい。

それに、マルチキャストデリゲートからメソッドを除去するのが面倒なんですよね。

とはいえ、デリゲートそのものがだめというわけではないので、コールバックはデリゲートを使うってのは間違いないです。

コメントを追加

Filtered HTML

  • ウェブページアドレスとメールアドレスは、自動的にハイパーリンクに変換されます。
  • 使用できるHTMLタグ: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <blockquote> <img>
  • 次のタグを使用してソースコード構文をハイライトすることができます。: <code>, <blockcode>, <c>, <cpp>, <drupal5>, <drupal6>, <java>, <javascript>, <php>, <python>, <ruby> The supported tag styles are: <foo>, [foo].
  • 行と段落は自動的に折り返されます。

Plain text

  • HTMLタグは利用できません。
  • ウェブページアドレスとメールアドレスは、自動的にハイパーリンクに変換されます。
  • 行と段落は自動的に折り返されます。
CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
イメージ CAPTCHA
Enter the characters shown in the image.
エラー | まさくらのブログ

エラー

サイトに予期せぬエラーが起こりました。しばらくたってから再度お試しください。