使用异步调用替代 bool TryGetX(out example)
Alternative to bool TryGetX(out example) with async calls
我真的很喜欢 bool TryGetX(out example)
的方式。问题是我想使用 GetKlinesAsync
并且它不允许我在异步方法中使用 out/ref 。你能向我推荐一种将它与异步 GetKlinesAsync 一起使用的方法吗?
我在想:
public (bool Success, IList<IOhlv> Candles) GetCandlesAsync(...)
意见?
片段
public class Client
{
// Works fine
public bool TryGetCandles(
string symbol,
KlineInterval timeInterval,
out IList<IOhlcv> candles,
DateTime? startTime = null,
DateTime? endTime = null,
int? limit = null)
{
var result = new BinanceClient().Spot.Market.GetKlines(symbol, timeInterval, startTime, endTime, limit);
candles = result.Data?.Select(x => x.ToCandle()).ToList();
return result.Success;
}
// Compile-time error
public async System.Threading.Tasks.Task<bool> TryGetCandlesAsync(
string symbol,
KlineInterval timeInterval,
out IList<IOhlcv> candles, // error CS1988: Async methods cannot have ref, in or out parameters
DateTime? startTime = null,
DateTime? endTime = null,
int? limit = null)
{
var result = await new BinanceClient().Spot.Market.GetKlinesAsync(symbol, timeInterval, startTime, endTime, limit).ConfigureAwait(false);
candles = result.Data?.Select(x => x.ToCandle()).ToList();
return result.Success;
}
}
当您使用 async
关键字时,编译器会生成一个 class / 状态机来保存所有局部变量并管理 async 和 await 模式. CLR 无法将 out/ref 参数的地址安全地存储在 class 的字段中(就像迭代器方法和其他生成的 classes 一样)。
有几个选项,但常见的方法是 return ValueTuple
public async Task<(bool success, IList<IOhlcv> candles)> TryGetCandlesAsync(...)
{
return (result.Success, candles)
}
...
var (success, candles) = await TryGetCandlesAsync();
if (success)
{
// do something candles;
}
如果你真的想要这一行,你可以使用模式匹配..虽然我个人会坚持使用单独的语句,因为在除了最简单的情况下,这会很快变得丑陋,并且有可能引入微妙的如果你偏离丢弃的问题
if (await TryGetCandlesAsync() is (bool success, _) result && success)
Console.WriteLine(result.candles);
// or
if (await TryGetCandlesAsync() is (true, _) result)
Console.WriteLine(result.candles);
我真的很喜欢 bool TryGetX(out example)
的方式。问题是我想使用 GetKlinesAsync
并且它不允许我在异步方法中使用 out/ref 。你能向我推荐一种将它与异步 GetKlinesAsync 一起使用的方法吗?
我在想:
public (bool Success, IList<IOhlv> Candles) GetCandlesAsync(...)
意见?
片段
public class Client
{
// Works fine
public bool TryGetCandles(
string symbol,
KlineInterval timeInterval,
out IList<IOhlcv> candles,
DateTime? startTime = null,
DateTime? endTime = null,
int? limit = null)
{
var result = new BinanceClient().Spot.Market.GetKlines(symbol, timeInterval, startTime, endTime, limit);
candles = result.Data?.Select(x => x.ToCandle()).ToList();
return result.Success;
}
// Compile-time error
public async System.Threading.Tasks.Task<bool> TryGetCandlesAsync(
string symbol,
KlineInterval timeInterval,
out IList<IOhlcv> candles, // error CS1988: Async methods cannot have ref, in or out parameters
DateTime? startTime = null,
DateTime? endTime = null,
int? limit = null)
{
var result = await new BinanceClient().Spot.Market.GetKlinesAsync(symbol, timeInterval, startTime, endTime, limit).ConfigureAwait(false);
candles = result.Data?.Select(x => x.ToCandle()).ToList();
return result.Success;
}
}
当您使用 async
关键字时,编译器会生成一个 class / 状态机来保存所有局部变量并管理 async 和 await 模式. CLR 无法将 out/ref 参数的地址安全地存储在 class 的字段中(就像迭代器方法和其他生成的 classes 一样)。
有几个选项,但常见的方法是 return ValueTuple
public async Task<(bool success, IList<IOhlcv> candles)> TryGetCandlesAsync(...)
{
return (result.Success, candles)
}
...
var (success, candles) = await TryGetCandlesAsync();
if (success)
{
// do something candles;
}
如果你真的想要这一行,你可以使用模式匹配..虽然我个人会坚持使用单独的语句,因为在除了最简单的情况下,这会很快变得丑陋,并且有可能引入微妙的如果你偏离丢弃的问题
if (await TryGetCandlesAsync() is (bool success, _) result && success)
Console.WriteLine(result.candles);
// or
if (await TryGetCandlesAsync() is (true, _) result)
Console.WriteLine(result.candles);