以前、非同期メソッド入門 (8) - コンパイラ要件と非同期メソッド入門 (9) - Awaitableパターンの自前実装で独自型のawaitの方法を紹介しました。TaskCompletionSource<T>という強力な助っ人もいることもあり、実際どれほど独自実装をするケースがあるのかは本当に未知数なのですが、実装時のヒントになるようコンパイラの要件を満たさなかった場合のエラーを載せておきます。
GetAwaiterを実装しない場合
await可能な型 (=ここではAwaitable型) は、GetAwaiterメソッドをインスタンスメソッドか拡張メソッドの形で持っていなければなりませんでした。GetAwaiterメソッドを持っていない場合にawaitしようとすると、以下のようなコンパイルエラーが表示されます。どうやら、「GetAwaiterメソッドがない」とは教えてくれないようです。
var result = await Awaitable<double>.Run(() => { Thread.Sleep(2000); //--- 計算したことにする return Math.PI; }); //--- ↑↑ AwaitableはGetAwaiterを実装しないとする
IsCompletedを実装しない場合
Awaiterになるためのひとつめの条件であるIsCompletedプロパティの実装をしなかった場合は、次のようなエラーになります。
また、次のようにコンパイラ要件に当たるものが何も実装されてないようなケースでもこのエラーが表示されます。これは非同期メソッド入門 (7) - 内部実装を覗くにもあるように、Awaiterのうち最初に利用されるものがIsCompletedプロパティであるからです。
class Awaiter<T>{}
INotifyCompletionを実装しない場合
Awaiterになるためのふたつめの条件であるINotifyCompletionインターフェースの実装をしなかった場合は、次のようなエラーになります。素直に「INotifyCompletionを実装していない」と教えてくれます。英語表記なのはVisual Studio 2012 RCで撮ったキャプチャだからだと信じています。
class Awaiter<T> { public bool IsCompleted{ get{ return true; } } }
GetResultを実装しない場合
Awaiterになるためのみっつめの条件であるGetResultメソッドの実装をしなかった場合は、次のようなエラーになります。この記事の最初から順に実装して行った場合、最後のこのエラーを取れば独自型のawaitをするための土台が完成したことになります。
class Awaiter<T> : INotifyCompletion { public bool IsCompleted{ get{ return true; } } public void OnCompleted(Action continuation){} }