我想写一个带out参数的async方法,像这样:
public async void Method1()
{
int op;
int result = await GetDataTaskAsync(out op);
}
我如何做到这一点在GetDataTaskAsync?
我想写一个带out参数的async方法,像这样:
public async void Method1()
{
int op;
int result = await GetDataTaskAsync(out op);
}
我如何做到这一点在GetDataTaskAsync?
当前回答
c# 7+的解决方案是使用隐式元组语法。
private async Task<(bool IsSuccess, IActionResult Result)> TryLogin(OpenIdConnectRequest request)
{
return (true, BadRequest(new OpenIdErrorResponse
{
Error = OpenIdConnectConstants.Errors.AccessDenied,
ErrorDescription = "Access token provided is not valid."
}));
}
返回结果使用方法签名定义的属性名。例句:
var foo = await TryLogin(request);
if (foo.IsSuccess)
return foo.Result;
其他回答
您可以通过使用TPL(任务并行库)而不是直接使用await关键字来做到这一点。
private bool CheckInCategory(int? id, out Category category)
{
if (id == null || id == 0)
category = null;
else
category = Task.Run(async () => await _context.Categories.FindAsync(id ?? 0)).Result;
return category != null;
}
if(!CheckInCategory(int? id, out var category)) return error
对于真正想要保持参数的开发人员,这里可能有另一种解决方法。
将参数更改为数组或List以封装实际值。记得在发送到方法之前初始化列表。返回后,在使用它之前一定要检查值是否存在。小心编码。
下面是@dcastro回答的代码,为c# 7.0修改了命名元组和元组解构,简化了符号:
public async void Method1()
{
// Version 1, named tuples:
// just to show how it works
/*
var tuple = await GetDataTaskAsync();
int op = tuple.paramOp;
int result = tuple.paramResult;
*/
// Version 2, tuple deconstruction:
// much shorter, most elegant
(int op, int result) = await GetDataTaskAsync();
}
public async Task<(int paramOp, int paramResult)> GetDataTaskAsync()
{
//...
return (1, 2);
}
有关新的命名元组、元组字面量和元组解构的详细信息,请参见: https://blogs.msdn.microsoft.com/dotnet/2017/03/09/new-features-in-c-7-0/
Alex在可读性上有很好的观点。同样,函数也具有足够的接口来定义返回的类型,并且还可以获得有意义的变量名。
delegate void OpDelegate(int op);
Task<bool> GetDataTaskAsync(OpDelegate callback)
{
bool canGetData = true;
if (canGetData) callback(5);
return Task.FromResult(canGetData);
}
调用者提供一个lambda(或一个命名函数),智能感知通过从委托复制变量名来提供帮助。
int myOp;
bool result = await GetDataTaskAsync(op => myOp = op);
这种特殊的方法类似于“Try”方法,如果方法结果为真,则设置myOp。否则,你不会关心myOp。
模式匹配来拯救!c# 9(我认为)之后:
// example of a method that would traditionally would use an out parameter
public async Task<(bool success, int? value)> TryGetAsync()
{
int? value = // get it from somewhere
return (value.HasValue, value);
}
像这样使用它:
if (await TryGetAsync() is (true, int value))
{
Console.WriteLine($"This is the value: {value}");
}