C# でイベントハンドラを yield return してみよう

以前、yield return に関してこんな記事を書いた。

C# の yield return の使い道 - カタチづくり

簡単に説明すると、直線作図の機能を下記のような状態遷移モデルで捉えて、これを IEnumerator を利用して実装しようと言う話。


この記事を受けて、実際に実装してくれた人がいた。ありがとうございます。
yield(いーるど)は、つまるところコルーチンなんだよね - Bug Catharsis


僕が書いたアイデアが簡潔に実装できていると思う。ただ、イベントハンドラを yield return してしまうほうがよりクールだと思うのでご紹介。

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

class MyForm : Form
{
  static void Main()
  {
    Application.Run( new MyForm() );
  }

  readonly List<Action<Graphics>> _entities = new List<Action<Graphics>>();
  IEnumerator<MouseEventHandler> _handler;

  public MyForm()
  {
    this.Paint += ( sender, e ) =>
    {
      foreach ( var draw in _entities ) draw( e.Graphics );
    };

    this.MouseClick += ( sender, e ) =>
    {
      if ( _handler != null ) {
        _handler.Current( this, e );
        this.MoveNext();
      }
    };

    _handler = this.DrawLines();
    this.MoveNext();
  }

  void MoveNext()
  {
    if ( !_handler.MoveNext() ) {
      _handler.Dispose();
      _handler = null;
    }
  }

  IEnumerator<MouseEventHandler> DrawLines()
  {
    while ( true ) {
      var p1 = new Point();
      var p2 = new Point();
      yield return ( sender, e ) => p1 = e.Location;
      yield return ( sender, e ) => p2 = e.Location;
      _entities.Add( g => g.DrawLine( new Pen( Brushes.Black ), p1, p2 ) );
      this.Invalidate();
    }
  }
}

DrawLines() 関数で MouseEventHandler を yield return しているところにご注目。何かの参考になれば幸いです。