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