英語で読む

次の方法で共有


コンパイラ エラー CS1986

'await' では、型に適切な 'GetAwaiter' メソッドがあることが必要です

次の例では CS1986 が生成されます。

using System.Runtime.CompilerServices;
using System;
using System.Threading.Tasks;

class Program
{
    static async Task M(MyTask<int> x)
    {
        var z = await x;
        System.Console.WriteLine(z);
    }
}

public class MyTask<TResult>
{
    readonly MyTaskAwaiter<TResult> awaiter;
    public MyTask(TResult value)
    {
        this.awaiter = new MyTaskAwaiter<TResult>(value);
    }
    public static MyTaskAwaiter<TResult> GetAwaiter() => throw new NotImplementedException();
}

public class MyTaskAwaiter<TResult> : INotifyCompletion
{
    TResult value;
    public MyTaskAwaiter(TResult value)
    {
        this.value = value;
    }
    public bool IsCompleted { get => true; }
    public TResult GetResult() => value;
    public void OnCompleted(Action continuation) => throw new NotImplementedException();
}

GetAwaiter メソッドは GetAwaiter という名前の非静的メソッドであり、かつ INotifyCompletion を実装するオブジェクトのインスタンスを返す必要があります。

GetAwaiter は、INotifyCompletion インターフェイス (と必要に応じて ICriticalNotifyCompletion インターフェイス) を実装し、かつそれ自体が 3 つのメンバーを公開する型を返す必要があります [1]:

bool IsCompleted { get; }
void OnCompleted(Action continuation);
TResult GetResult(); // TResult can also be void

このエラーを解決するには

この例で CS1986 が発生するのは、GetAwaiter メソッドが static であるためです。 このエラーを修正するには、static 修飾子を削除します (そしてメソッドを正しく実装します)。

public class MyTask<TResult>
{
    readonly MyTaskAwaiter<TResult> awaiter;
    public MyTask(TResult value)
    {
        this.awaiter = new MyTaskAwaiter<TResult>(value);
    }
    public MyTaskAwaiter<TResult> GetAwaiter() => awaiter;
}

関連項目

[1] 何でも待機する