C# Error CS1986 – ‘await’ requires that the type {0} have a suitable ‘GetAwaiter’ method

C# Error

CS1986 – ‘await’ requires that the type {0} have a suitable ‘GetAwaiter’ method

Reason for the Error & Solution

‘await’ requires that the type have a suitable ‘GetAwaiter’ method

Example

The following sample generates 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();
}

A GetAwaiter method must be a non-static method named GetAwaiter and return an instance of an object that implements INotifyCompletion.

A GetAwaiter needs to implement the INotifyCompletion interface (and optionally the ICriticalNotifyCompletion interface) and return a type that itself exposes three members [1]:

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

To correct this error

The reason CS1986 is raised in the example is that the GetAwaiter method is static. To correct this error, remove the static modifier (and correctly implement the method):

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

[1]