Converting generic method to async causing issues with generic params

In a static class called StaticHelper, I have the following generic static method:

public static class StaticHelper
{
    public static TResponse GenericMethod<TResponse, TRequest>(TRequest request,
                                                           Func<TRequest, TResponse> method)
    where TRequest  : BaseRequest
    where TResponse : BaseResponse, new()
{
    // ...
}

Func<TRequest, TResponse> method is the name of the method that gets invoked by GenericMethod. GenericMethod is used as a wrapper around WCF methods to log requests/responses, etc:

public override SomeCustomResponse Request(SomeCustomRequest request)
{
    // GenericMethod above called here
    return StaticHelper.GenericMethod(request, ExecuteRequest));
}

private SomeCustomResponse ExecuteRequest(SomeCustomRequest request)
{
    // ...
}

I am now trying to create it's async equivalent:

public static async Task<TResponse> GenericMethodAsync<TResponse, TRequest>(TRequest request,
                                                           Func<TRequest, TResponse> method)
    where TRequest  : BaseRequest
    where TResponse : BaseResponse, new()
{
    // ...
}

// i have removed the override keyword here as I don't need it
public async Task<SomeCustomResponse> Request(SomeCustomRequest request)
{
    // GenericMethodAsync above called here
    return await StaticHelper.GenericMethodAsync(request, ExecuteRequest));
}

private async Task<SomeCustomResponse> ExecuteRequest(SomeCustomRequest request)
{
    // ...
}

This ends up in two errors:

In public async Task<SomeCustomResponse> Request(SomeCustomRequest request) (2nd async method):

1) The type Task<SomeCustomResponse> cannot be used as type parameter 'TResponse' in the generic type or method 'StaticHelper.GenericMethodAsync<TResponse, TRequest>(TRequest, Func<TRequest, TResponse>)'. There is no implicit reference conversion from Task<SomeCustomResponse> to BaseResponse

...and:

2) Task<SomeCustomResponse> must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'TResponse' in the generic type or method StaticHelper.GenericMethodAsync<TResponse, TRequest>(TRequest, Func<TRequest, TResponse>)

Update: The answer by René below makes the errors disappear. I now have a new one:

Cannot implicitly convert type 'Task<TResponse>' to 'TResponse'

The offending line is in StaticHelper.GenericMethodAsync which tries to execute the Func:

var response = method(request); // <-- Cannot implicitly convert type 'Task<TResponse>' to 'TResponse'

...and obviously, the solution is to simply await that:

var response = await method(request);

1 answer

  • answered 2018-07-12 07:35 René Vogt

    You need to change the declaration of GenericMethodAsync, because the return type of the method (ExecuteRequest) now is Task<TResponse> instead of TResponse:

    public static async Task<TResponse> GenericMethodAsync<TResponse, TRequest>(
                         TRequest request,
                         Func<TRequest, Task<TResponse>> method) // <-- change here
                                where TRequest  : BaseRequest
                                where TResponse : BaseResponse, new()
    {
        // ...
    }
    

    And consider to rename ExecuteRequest to ExecuteRequestAsync, too.

    And of course you have to change the use of method inside GenericMethodAsync now accordingly:

    var response = await method(request);