Selim Yildiz
Selim Yildiz

Reputation: 5370

Void task with generics in C#

I would like to reuse the following static generic Profile function in my application:

private static async Task<T> Profile<T>(Func<Task<T>> func, string operation)
{
    Console.WriteLine($"{operation} is called");
    return await func();
}

And I have the following interface to implement:

public interface ICustomerOperations
{
    Task<Customer> GetCustomerAsync(string id);

    Task DeleteCustomerAsync(string id);
}

I can use Profile method with GetCustomerAsync without any problem.

public async Task<Customer> GetCustomer(string id)
{
    return await Profile(() => _customerOperations.GetCustomerAsync(id), $"GetCustomerAsync");
}

However when I try to use Profile with DeleteCustomerAsync

public async void DeleteCustomer(string id)
{
    await Profile(() => _customerOperations.DeleteCustomerAsync(id), $"DeleteCustomerAsync");
}

Build failed:

The type arguments for method 'CrmService.Profile(Func<Task>, string)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

So my question is how can I reuse Task<T> with void?

Upvotes: 0

Views: 850

Answers (2)

Stephen Cleary
Stephen Cleary

Reputation: 456417

You can create an overload without duplicating the method:

private static Task Profile(Func<Task> func, string operation)
{
  return Profile<object>(async () => { await func(); return null; }, operation);
}

Upvotes: 4

SomeBody
SomeBody

Reputation: 8743

A simple solution is to duplicate your method:

private static async Task Profile(Func<Task> func, string operation)
{
    Console.WriteLine($"{operation} is called");
    await func();
}

I think duplicating your method is cleaner than doing some hacks like this:

public async void DeleteCustomer(string id)
{
    await Profile(async () => { await _customerOperations.DeleteCustomerAsync(id); return 0; }, $"DeleteCustomerAsync");
}

Upvotes: 1

Related Questions