Task.FromResult でシングルトンを返すことができる
Task.FromResult<TResult>(TResult) で、常に新しいインスタンスを作成するのではなく、キャッシュされた Task<TResult> インスタンスを返すことができるようになりました。
以前の動作
以前のバージョンでは、Task.FromResult<TResult>(TResult) を使用すると、T
の型または結果値に関係なく、常に新しい Task<TResult> が割り当てられていました。
新しい動作
一部の T
型と一部の結果値については、Task.FromResult<TResult>(TResult) で、新しいオブジェクトを割り当てるのではなく、キャッシュされたシングルトン オブジェクトを返すことができます。 たとえば、Task.FromResult(true)
を呼び出すごとに、既に完了している同じ Task<bool>
オブジェクトが返されるようになります。
導入されたバージョン
.NET 6
破壊的変更の種類
この変更は、バイナリの互換性に影響を与える可能性があります。
変更理由
多くの開発者は Task.FromResult<TResult>(TResult) に対して、このようなキャッシュを既に実行した非同期メソッドと同様に動作することを期待しています。 割り当ての動作について知っている開発者は、多くの場合、共通して使用されるこれらの値に対して常に割り当てをするパフォーマンスのコストを回避するために、独自のキャッシュを維持していました。 次に例を示します。
private static readonly Task<bool> s_trueTask = Task.FromResult(true);
現在、このようなカスタム キャッシュは、Boolean や小さい Int32 の値などの値には必要なくなりました。
推奨アクション
参照の等価性を使用して、1 つの Task
インスタンスが別の Task
インスタンスと同じかどうかを確認する場合を除いて、この変更の影響を受けることはないはずです。 このような参照の等価性を使用しており、このチェックを続行する必要がある場合は、次のコードを使用して、常に一意の Task<TResult> インスタンスが返されるようにする必要があります。
private static Task<T> NewInstanceFromResult<T>(T result)
{
var tcs = new TaskCompletionSource<T>();
tcs.TrySetResult(result);
return tcs.Task;
}
注意
このパターンは、Task.FromResult(result)
を使用するよりもはるかに非効率的で、本当に必要な場合を限いて避ける必要があります。
影響を受ける API
.NET