override時の戻り値がTaskで、awaitが無い(同期実行)の場合

C#でClassの継承時に、overrideしている場合、awaitすることが想定される場合、戻り値をTaskにすることになります。
しかし、派生クラスによっては、await不要で、同期実行される派生クラスもあります。

public override async Task DoSometing()
{
dummyCount++;
return;
}

今までこんな感じで書いていたのですが、VisualStudioでは、警告が出ます。
「CS1998 : この非同期メソッドには’await’演算子が無いため・・・」

どうすればいいのかちょっと調べてみたところ、Task.CompletedTaskを返してあげればよいとのこと。
この改造をすると、速度がどうなるのか気になったので調べてみた。
まあ、同じ速度ならいいのだけど、万一遅くなったらいやだなぁと。

結果から書くと、速度はむしろ早くなった。うん。素晴らしい。
今後はこの書き方をしよう。(以下コードのCompletedTaskClass.DoSometing)

static int dummyCount;

public abstract class BaseClass
{
    public abstract Task DoSometing();
}

public class AsyncClass :BaseClass
{
    public override async Task DoSometing()
    {
        dummyCount++;
        return;
    }
}


public class CompletedTaskClass : BaseClass
{
    public override Task DoSometing()
    {
        dummyCount++;
        return Task.CompletedTask;
    }
}

[Benchmark]
public async Task AsyncBench()
{
    var instance = new AsyncClass();
    await instance.DoSometing();
}

[Benchmark]
public async Task CompletedTaskBench()
{
    var instance = new CompletedTaskClass();
    await instance.DoSometing();
}
.net 5.0
|             Method |     Mean |    Error |   StdDev |
|------------------- |---------:|---------:|---------:|
|         AsyncBench | 26.90 ns | 0.561 ns | 0.787 ns |
| CompletedTaskBench | 12.07 ns | 0.232 ns | 0.249 ns |

なお、戻り値がTask<T>の場合、Task.FromResultを使うらしい。
Task.FromResult も、asyncの場合より速かったです。

投稿日:
カテゴリー: C#

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です