delegate の派生クラスが作りたいと思った時

C# で書けないってだけなので、作ればいいんですけども。たとえば特定のメソッドを非同期処理化するヘルパクラスなんぞを作った場合に困るんですよね。

[AsyncCall]
public int test(int arg)
{
  ...
}

なんて感じで属性を設定すると、

  {
    // int test(int) を int? で受け取る
    int? result = test(10);

    // 結果がでるまで待機するループ
    Console.Write("Waiting...");
    while (!result.HasValue)
    {
      Console.Write(".");
      Thread.Sleep(200);
    }

    Console.WriteLine(" test(10) = {0}", result.Value);
  }

みたいなことが出来るとか。たとえば実装はこんな感じ

public struct ASyncResult<T, U> { private readonly Converter<T, U> action; private IAsyncResult ar; public ASyncResult(Converter<T, U> action) { this.action = action; this.ar = null; } public ASyncResult(Converter<T, U> action, T arg) : this(action) { this.Execute(arg); } public ASyncResult<T, U> Execute(T arg) { if (this.ar == null) { this.Invoke(arg); return this; } else { return new ASyncResult<T, U>(this.action, arg); } } protected void Invoke(T arg) { this.ar = this.action.BeginInvoke(arg, null, null); } public bool HasValue { get { return this.IsCompleted; } } public U Value { get { return this.action.EndInvoke(this.ar); } } public bool IsInvoked { get { return (this.ar != null); } } public bool IsCompleted { get { return (this.ar != null) ? this.ar.IsCompleted : false; } } public bool CompletedSynchronously { get { return (this.ar != null) ? false : this.ar.CompletedSynchronously; } } public static explicit operator U(ASyncResult<T, U> result) { return result.Value; } public static implicit operator ASyncResult<T, U>(Converter<T, U> action) { return new ASyncResult<T, U>(action); } }

int? へ代入可能にするのは難しそうだったので、Nullable っぽいインターフェスにしかなっていないとか、使うときに

  ASyncResult<int, int> result = test_(10);

  static ASyncResult<int, int> test_(int value)
  {
     return ((ASyncResult<int, int>) test).Execute(value);
  }

とかしないといけないので、かなーりダメなかんじになってしまっています。せめて、

  ASyncResult<int, int> result = ((ASyncResult<int, int>) test)(10);

みたいに、ASyncResult'2 型のインスタンスに対して delegate のように呼び出せるぐらいは欲しいかもしれない。あと、Execute() の引数が複数になったときに、object[] やらパラメータ保持用の構造体を渡すのは何だかなーになっちゃう。こういうときこそ __arglist*1 か?

*1:params のより強力なやつみたいなもので、型の異なる可変長な引数を受け取ることができる。