13

TaskまたはTask<TResult>オブジェクトは待機可能であるため、戻り値がTaskまたはTask<TResult>であるオブジェクトに対してawaitキーを使用できます。TaskまたはTask<TResult>は、最も頻繁に使用される待機可能なオブジェクトです。

独自の待機可能なオブジェクトを定義することもできます。オブジェクトには、以下の資格が必要です。

  1. GetAwaiter()メソッド(インスタンスメソッドまたは拡張メソッド)があります。
  2. そのGetAwaiter()メソッドはawaiterを返します。次の場合、オブジェクトは待機者です。
    • INotifyCompletionまたはICriticalNotifyCompletionインターフェイスを実装します。
    • ゲッターがあり、ブール値を返すIsCompletedがあります。
    • voidまたは結果を返すGetResult()メソッドがあります。

私の質問は、なぜマイクロソフトがこれらの待機可能なオブジェクトを制約するためのインターフェイスを提供しなかったのかということです。待機可能なオブジェクトを実装するための現在のメソッドは少し複雑です。

4

3 に答える 3

13

Lucian Wischik のブログ投稿で最もよく答えられているのはなぜ非同期メソッドがタスクを返す必要があるのですか?

要約すると (そして、私はブログ投稿の正義を行っているわけではありません。それを読んでください)、問題はTaskすでに存在しているため、インターフェイスを導入することは

  • すべての内部メソッドをインターフェイスに変更する必要があり、ブレークの変更が必要になるため、フレームワークの人々が喜んで行うことはほとんど不可能です。
  • プログラマーとして、返すかインターフェイスにするかを常に決定する必要がありTaskますが、この決定はあまり重要ではありません。
  • コンパイラは常に具象型を必要とするため、メソッドからインターフェイスを返したとしても、それは としてコンパイルされTaskます。

上記の影響は非常に大きいため、インターフェイスを提供する意味がありません。

于 2012-12-28T06:04:17.270 に答える
5

これは、キーワードに対して行ったことと一致しています ( C# 言語仕様foreachのセクション 8.8.4 「foreach ステートメント」を参照してください)。

基本的に、それはダックタイピングです。MoveNext型がメソッドとプロパティを実装している場合Current、C# コンパイラがオブジェクトによって公開されたシーケンスを反復処理する方法を知るために必要なのはそれだけです。

これは、コレクション初期化子にも適用されます (C# 言語仕様「コレクション初期化子」のセクション 7.6.10.3 を参照)。唯一の要件は、型がSystem.Collections.IEnumerableインターフェイスを実装し、メソッドを持っているAddことです。

つまり、awaitキーワードは以前の先例に固執するだけで、特定のインターフェイスの実装を必要とせず (インターフェイスを使用することを選択した場合は、これらのメソッドが提供されます)、コンパイラが認識できるメソッドのパターンにすぎません。

于 2012-12-28T05:44:53.373 に答える