1. ホーム
  2. c#

[解決済み] Task<int>はどうやってintになるのですか?

2022-06-26 09:16:36

質問

このような方法があります。

async Task<int> AccessTheWebAsync()
{ 
    HttpClient client = new HttpClient();

   Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");

   // You can do work here that doesn't rely on the string from GetStringAsync.
   DoIndependentWork();

   string urlContents = await getStringTask;
   //The thing is that this returns an int to a method that has a return type of Task<int>
   return urlContents.Length;
}

の間で暗黙のうちに変換が行われるのでしょうか? Task<int>int ? そうでない場合、何が起こっているのでしょうか? どのように動作するように実装されていますか?

どのように解決するのですか?

<ブロッククオート

Task<>とintの間で暗黙の変換が行われるのでしょうか?

いいえ。これは単に async / await が動作します。

として宣言されたメソッドはすべて async の戻り値の型を持たなければなりません。

  • void (可能であれば避けてください)
  • Task (完了/失敗の通知以上の結果はない)
  • Task<T> (型の論理結果に対して T を非同期で返す)

コンパイラは適切なラッピングをすべて行ってくれます。ポイントは、あなたが を非同期で を返していることです。 urlContents.Length - を返すだけのメソッドは作れません。 int を返すだけのメソッドにすることはできません。 await 式にぶつかったときに返されるからです。そのため、代わりに Task<int> を返し、これは非同期メソッド自身が完了したときに完了します。

なお await はその逆を行います - それは を解き放ちます。 a Task<T>T の値に変換することで、この行が機能するようになります。

string urlContents = await getStringTask;

...しかし、もちろんそれは非同期でアンラップされます。 Result を使うとタスクが完了するまでブロックしてしまいます。( await はawaitableパターンを実装した他の型をアンラップすることができますが Task<T> は最もよく使うものでしょう)。

この二重のラップ/アンラップは、非同期がとてもコンポーザブルであることを可能にするものです。例えば、私はあなたのメソッドを呼び出す別の非同期メソッドを書き、その結果を2倍にすることができます。

public async Task<int> AccessTheWebAndDoubleAsync()
{
    var task = AccessTheWebAsync();
    int result = await task;
    return result * 2;
}

(あるいは、単に return await AccessTheWebAsync() * 2; でもよい)。