Home > Software engineering >  Asynchronous operation returning a result with method inheritance
Asynchronous operation returning a result with method inheritance

Time:01-18

I have a simple question about asynchronous operations. I have a composition class used to encapsulate an HttpClient instance. This class have an abstract base class to avoid code redundancy.

My problem occur when I'm trying to override a base method doing a part of the job in the derived method who is doing additional operations.

To be clearer I have:

Base method:

    /// <summary>
    /// Execute a Typed GET Request and returning <typeparamref name="TResponse"/> result.
    /// </summary>
    /// <typeparam name="TResponse">Response specified type.</typeparam>
    /// <param name="route">Uri string to request.</param>
    /// <param name="path">Path parameters to provide to the <paramref name="route"/>.</param>
    /// <param name="query">Query parameters to provide to the <paramref name="route"/>.</param>
    /// <returns>The <see cref="Task"/> that represents the asynchronous operation containing <typeparamref name="TResponse"/> response object.</returns>
    /// <exception cref="HttpRequestException">Raised if the Http request failed.</exception>
    public virtual async Task<TResponse?> GetAsync<TResponse>(string route, Dictionary<string, string>? path = null, Dictionary<string, string>? query = null)
    {
        using HttpResponseMessage response = await _httpClient.GetAsync(BuildUri(route, path, query));
        response.EnsureSuccessStatusCode();

        return await response.Content.ReadFromJsonAsync<TResponse>(new JsonSerializerOptions() { PropertyNameCaseInsensitive = true });
    }

Derived method:

    /// <inheritdoc/>
    public override async Task<TResponse?> GetAsync<TResponse>(string route, Dictionary<string, string>? path = null, Dictionary<string, string>? query = null)
    {
        var token = await GetBearerToken();
        base._httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
        return base.GetAsync<TResponse>(route, path, query);
    }

So the base class method have the http request responsibility and the derived method is adding additional pre-treatments to configure the httpClient with the required headers and others. The error occur on the return, I tried both:

return base.GetAsync<TResponse>(route, path, query);

with the error: Impossible to convert type Task<TResponse?> into TResponse?

and

return await base.GetAsync<TResponse>(route, path, query);

with the error: Impossible to convert type TResponse into TResponse?

I'm not understanding why, when I'm awaiting the result, a cast is done casting Nullable<TResponse> into TResponse in the derived method, knowing the fact that base method is returning Task<TResponse?>.

Thanks in advance.

Edit:

@Selvin and @Enigmativity got the right answer here adding a class constraint to the generic TResponse type in the method definition of both base and derived method resolve the issue, Thanks for your help!

CodePudding user response:

You method needs to constrain TResponse to a class:

public virtual async Task<TResponse?> GetAsync<TResponse>(
        string route,
        Dictionary<string, string>? path = null,
        Dictionary<string, string>? query = null)
    where TResponse : class
  • Related