次の方法で共有


Task.FromResult でシングルトンを返すことができる

Task.FromResult<TResult>(TResult) は、常に新しいインスタンスを作成するのではなく、キャッシュされた Task<TResult> インスタンスを返す可能性があります。

以前の動作

以前のバージョンでは、Task.FromResult<TResult>(TResult)では、Task<TResult>の種類や結果値に関係なく、常に新しいTが割り当てられます。

新しい動作

一部の 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