与异步调用相比,可选择bool TryGetX(out示例)



我真的很喜欢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关键字时,编译器生成一个类/状态机来保存所有的局部变量并管理异步和等待模式。CLR无法安全地将out/ref形参的地址存储在类的字段中(就像迭代器方法和其他生成的类一样)。

有几个选项,但一个常见的方法是返回一个ValueTuple

public async Task<(bool success, IList<IOhlcv> candles)> TryGetCandlesAsync(...)
{
return (result.Success, candles)
}

...
var (success, candles) = await TryGetCandlesAsync();
if (success)
{
// do something candles;
}

如果你真的想要这一行,你可以使用模式匹配。尽管就我个人而言,我会坚持使用单独的语句,因为除了最简单的情况外,这将很快变得丑陋,并且如果偏离了discards

,可能会引入微妙的问题。
if (await TryGetCandlesAsync() is (bool success, _) result && success)
Console.WriteLine(result.candles);
// or
if (await TryGetCandlesAsync() is (true, _) result)
Console.WriteLine(result.candles);

最新更新