Search code examples
c#async-awaittaskextension-methods

How to create a generic extension method for async methods?


I am trying to create a .WithDelay(seconds); method which I can add at the end of async method calls.

The issue I get is the async method is called first then the delay happens, I want it the other way around, without switching the order of the call.

For example, I want await MyMethod().WithDelay(seconds); rather than await WithDelay(seconds).MyMethod();.

Here is what I have so far, it calls the method first:

public async static Task<T> WithDelay<T>(this Task<T> task, int delay) {
  await Task.Delay(delay);
  return await task;
}

I expect the delay to happen first, then the actual method to run.


Solution

  • I want it the other way around, without switching the order of the call.

    This isn't possible, because the C# language only supports extension methods on types, not methods.

    The closest you can get is an extension method on delegates:

    public static async Task<T> WithDelay<T>(this Func<Task<T>> func, int delay) {
      await Task.Delay(delay);
      return await func();
    }
    

    The usage still ends up being awkward:

    // Either:
    Func<Task<MyType>> func = MyMethod;
    var result = await func.WithDelay(1000);
    
    // or (assuming "using static"):
    var result = await WithDelay(MyMethod, 1000);
    
    // What you really want, not currently possible:
    // var result = await MyMethod.WithDelay(1000);
    

    For type-related situations like this, it can help to solve the problem synchronously first, then convert that solution to async. If the language prevents a good synchronous solution, then it will likely prevent a good asynchronous solution.

    There is a proposal for extension methods on methods, but it's not part of the language today.