R.Tanaka.Ichiro's Blog

主にC# な話題です

目次

Blog 利用状況

ニュース

イベントに空デリゲートを仕込ませてみる

http://blogs.wankuma.com/nakamura/archive/2008/11/25/162049.aspx
イベントを発生させるメソッドの実装(2)(Nakamura Blogより)

上記を読んで、面白いなー、と思って僕も試してみました。


public class Sample {
  public event EventHandler<HelloEventArgs> Hello = delegate {};
  protected virtual void OnHello(HelloEventArgs e) {
    Hello(this, e); // null にならないからチェックが不要
  }
}


確かに、インスタンス上から Hello を null する術がないということで、イベント発行時に null チェックが不要になる点では、すっきり書くことができますね。

また、毎回比較演算するよりは高速に処理できる筈・・・

でも、イベントの登録が 1 件増えるから、常に空の呼び出しが 1 件増えることとトレードオフな関係ですよね?
さて、どちらが高速なのでしょうか?

自分のメソッド内で、null 比較演算をする方が速いのか、イベントの空呼び出しによるオーバーヘッドの方が遅いのか?w


class TestClass {
  static void Method() {
    var t = new System.Diagnostics.Stopwatch();
    ISample[] a = { new Sample1(), new Sample2() };
    foreach(var i in Enumerable.Range(1, 5)) {
      Console.WriteLine(i.ToString() + "回目のテスト-----");
      foreach(var x in a) {
        x.Hello += (sender, e) => {};
        t.Reset();
        t.Start();
        foreach(var j in Enumerable.Range(0, 10000000)) x.Fire();
        t.Stop();
        Console.WriteLine(t.ElapsedTicks);
      }
    }
  }
}

public interface ISample {
  event EventHandler<EventArgs> Hello;
  void Fire();
}

public class Sample1 : ISample {
  public event EventHandler<EventArgs> Hello = delegate {};
  public void Fire() {
    Hello(this, EventArgs.Empty);
  }
}
public class Sample2 : ISample {
  public event EventHandler<EventArgs> Hello;
  public void Fire() {
    if (Hello != null) Hello(this, EventArgs.Empty);
  }
}


1回目のテスト-----
18016811
11843868
2回目のテスト-----
19669451
18374921
3回目のテスト-----
22624583
21159129
4回目のテスト-----
25875112
24878342
5回目のテスト-----
29027337
27788239


null の比較演算を毎回行う方が僅かながら速いんですね。
まあ、殆ど気にならないくらいですけど。

どちらの書き方が良いのかは、ちょっと結論ができませんが、僕は今まで通り後者でいこうかなー

投稿日時 : 2008年11月25日 14:10

Feedback

# re: イベントに空デリゲートを仕込ませてみる 2008/11/25 14:47 黒龍

空呼び出しの発生は失念してました。ちゃんと試さなきゃですね…。

# re: イベントに空デリゲートを仕込ませてみる 2008/11/25 15:32 R・田中一郎

興味深い方法だったので、僕としても明確なメリットがあるなら使ってみたいと思っています。

そういう意味で、きちんと結論を出しておきたくて、nakamura さんにも、失礼ながらずけずけと質問させていただきました。

実際、速度の面で有利であるかもしれない意見はありがたかったです。

# re: イベントに空デリゲートを仕込ませてみる 2008/11/25 16:10 なかむら

私もRさんと同じで、普段は後者(null比較)で書いています。
今回は「こういうやり方もあるんだなぁ」とちょっと関心したので紹介してみました。

# re: イベントに空デリゲートを仕込ませてみる 2008/11/25 19:59 R・田中一郎

とても興味深い情報をありがとうございました。
もうちょっと遊んでみます。

# re: イベントに空デリゲートを仕込ませてみる 2008/11/26 0:17 れい

コードの綺麗さとか長さっていうのはちょっとずつ、確実に効いてくるボディーブロー(?)のようなものですよね。

例えば、高速化のために「ループの展開」をする場合もありますが、展開しすぎるとコードがメモリを圧迫してトータルで遅くなる場合も多いわけで。

デリゲートがnullかどうかを比較してから呼び出すのも同じで、
それだけを単純ループで比較したら空呼び出しを入れておく方が遅いでしょうが、
現実のアプリケーションで使った場合、どちらが速いかは微妙であろうと思います。

こういうことは非常に多くて、実際にやってみないとわからない、というのは困ります。
大抵の場合はこうしておけばいい、みたいなことを偉い人が言ってくれるといいのですが。

誰も何も言ってくれないので、私はとりあえず「短いコードはトータルでは結構早い」という方針を取っています。
同じ意味ならキータイプの少ないコードを選ぶ。

なので、イベント入れたり出したりするようなコードを書く時は空呼び出しを最初に入れておく派です。

# re: イベントに空デリゲートを仕込ませてみる 2008/11/26 8:31 渋木宏明(ひどり)

速度以外の面も評価するべきです。

(見た目の)コードの複雑度に注目すると

・条件判断が一つ減る
・代入が一つ増える

ことになります。

微妙な差ですが、代入よりも条件判断の方が複雑度は↑名はずなので、コードの複雑度も僅かながら軽減していると思います。

# re: イベントに空デリゲートを仕込ませてみる 2008/11/26 12:27 なちゃ

若干別の観点だと、nullチェックするやり方が既に一般的に広まっているため、
nullチェックが無いのが正しいのか間違いなのか分かりにくい、
初心者がはじめにこちらをみると、単にnullチェックがいらないと誤解する可能性がある、
ってのもちょっとあったりします。

# re: イベントに空デリゲートを仕込ませてみる 2008/11/26 13:13 R・田中一郎

れい さん
渋木宏明(ひどり) さん

速度の面は、メリットもデメリットもないと考えて良いと思いますね。
実際、メソッドアウトすると速度が遅くなるという前提でプログラミングする人は殆どいない訳で、速度の検証をしたのは逆にそれを明らかにするという目的もありました。

また、継承などの理由で、イベントの着火は On~ で行う流儀があるので、null 判定を書いても 1 メソッドだけに包めてしまう点で、コードがきれいに書けることも、あまりメリットがないのかなー、とも思ったりしてます。

コードの書き方として、そのメソッドの独立性を重視した場合は、直前で null 判定する書き方の方が確実です。
という意味で、僕は null かなーと思ってますけど、うーむ、悩むなぁ・・・

# re: イベントに空デリゲートを仕込ませてみる 2008/11/26 13:15 R・田中一郎

なちゃ さん

それもありますよね。
イベントが初期化されているかどうかを確認しないといけないですもんね。

# re: イベントに空デリゲートを仕込ませてみる 2008/11/26 18:16 渋木宏明(ひどり)

>そのメソッドの独立性

も、ほんの僅かな差ですね。

着火メソッドの実装は、どーあってもイベント本体?に依存しちゃうわけで。

# re: イベントに空デリゲートを仕込ませてみる 2008/11/27 23:39 R・田中一郎

そうかなぁ。

以下のコードがあったとしますよね。

public event EventHandler<EventArgs> Hello = delegate {};
public void Fire() {
  Hello(this, EventArgs.Empty);
}

この一部がコンストラクタに書かれている場合よりは、上記のようにまとまっている方が・・・

これも僅かな差ですねw

# イベントに空デリゲートを仕込ませてみる(その2) 2008/11/28 14:29 R.Tanaka.Ichiro's Blog

イベントに空デリゲートを仕込ませてみる(その2)

# イベントに空デリゲートを仕込ませてみる(その2) 2008/12/02 15:27 R.Tanaka.Ichiro's Blog

イベントに空デリゲートを仕込ませてみる(その2)

タイトル  
名前  
Url
コメント