向泛型方法传入无返回值Task委托时:无法将void转换为Task
问题描述
我有一个接受委托的泛型异步方法ExecuteWithRetryAsync<T>,定义如下:
public async Task<T> ExecuteWithRetryAsync<T>(Func<Task<T>> action) { try { return await _retryPolicy.ExecuteAsync(async () => { return await action(); }); } catch (HttpRequestException) { return default(T); //log this to queue } }
调用返回泛型Task<T>的CheckSaleAsync方法时一切正常:
var saleCheckResult = await ExecuteWithRetryAsync(async () => await _client.CheckSaleAsync(SaleId));
该方法定义为:
public virtual System.Threading.Tasks.Task<SaleCheckResult> CheckSaleAsync(string saleId) { return CheckSaleAsync(saleId, System.Threading.CancellationToken.None); }
但当尝试调用返回非泛型Task的DisableMachineAsync方法时:
public virtual System.Threading.Tasks.Task DisableMachineAsync(string machineId) { return DisableMachineAsync(machineId, System.Threading.CancellationToken.None); }
使用相同方式调用出现错误**“无法从用法推断方法的类型参数,请尝试显式指定参数”;显式指定类型为Task后,又出现“无法将void隐式转换为Task”**的错误。无法将void作为类型参数,请问如何正确传递委托以完成编译?
解决方案
方法1:新增非泛型重载方法
这是最规范的处理方式,专门新增一个适配非泛型Task的重载方法:
public async Task ExecuteWithRetryAsync(Func<Task> action) { try { await _retryPolicy.ExecuteAsync(async () => { await action(); }); } catch (HttpRequestException) { // 执行日志入队逻辑 } }
调用时直接传入委托即可,无需额外处理:
await ExecuteWithRetryAsync(async () => await _client.DisableMachineAsync(MachineId));
方法2:调用时包装委托(临时适配)
如果不想新增方法,可以将无返回值的委托包装为返回占位类型的泛型委托:
用object作为占位类型
await ExecuteWithRetryAsync<object>(async () => { await _client.DisableMachineAsync(MachineId); return null; });
用Unit类型(推荐,需引用System.Reactive)
Unit是专门用于表示无返回值的类型,语义更清晰:
await ExecuteWithRetryAsync<Unit>(async () => { await _client.DisableMachineAsync(MachineId); return Unit.Default; });
内容的提问来源于stack exchange,提问作者Vladimir
相关产品推荐
相关产品推荐

