You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何判断LanguageExt.Core的Result<T>是否出错以触发Polly重试

}

```csharp
private async Task<Result<Unit>> ConnectAsync(Uri uri)
{
    if (_ws is not null)
    {
        return new Result<Unit>(new InvalidOperationException("The websocket client is already connected"));
    }

    var ws = Options.ClientFactory();
    try
    {
        using var connectTimeout = new CancellationTokenSource(Options.Timeout);
        await ws.ConnectAsync(uri, connectTimeout.Token).ConfigureAwait(false);
    }
    catch
    {
        ws.Dispose();
        return new Result<Unit>(new InvalidOperationException("Failed to connect to the endpoint"));
    }

    await _connectedEvent.InvokeAsync(new ConnectedEventArgs(uri));

    _ws = ws;
    IsRunning = true;

    return Unit.Default;
}

解决方案

1. 用IfFailThrow()直接抛出异常

LanguageExt的Result<T>自带IfFailThrow()扩展方法,一旦Result处于失败状态,就会自动抛出内部的异常,直接触发Polly的重试逻辑,写法最简洁:

private async Task RunAsync(Uri uri)
{
    var result = await ConnectAsync(uri);
    // 失败时直接抛出异常,无需额外判断
    result.IfFailThrow();

    // 后续正常业务逻辑
    ...
}

2. 用Match做日志后再抛出

如果需要先记录错误日志再抛出异常,用Match方法是更贴合LanguageExt函数式设计的方式,它能分别处理成功和失败分支:

private async Task RunAsync(Uri uri)
{
    var result = await ConnectAsync(uri);
    
    result.Match(
        _ => { /* 成功时的逻辑,这里不需要可以留空 */ },
        ex => {
            _logger.LogError(ex, "连接端点出错");
            throw ex; // 抛出异常触发Polly重试
        }
    );

    ...
}

3. 优化ConnectAsync的Result创建方式

你当前手动new Result<Unit>(异常)的写法不够规范,LanguageExt提供了静态方法来创建Result,更符合函数式风格:

  • 成功结果:直接返回Unit.Default(LanguageExt支持隐式转换为Result<Unit>.Success)
  • 失败结果:用Result<Unit>.Fail(异常)创建

优化后的ConnectAsync代码:

private async Task<Result<Unit>> ConnectAsync(Uri uri)
{
    if (_ws is not null)
    {
        return Result<Unit>.Fail(new InvalidOperationException("WebSocket客户端已连接"));
    }

    var ws = Options.ClientFactory();
    try
    {
        using var connectTimeout = new CancellationTokenSource(Options.Timeout);
        await ws.ConnectAsync(uri, connectTimeout.Token).ConfigureAwait(false);
    }
    catch
    {
        ws.Dispose();
        return Result<Unit>.Fail(new InvalidOperationException("连接端点失败"));
    }

    await _connectedEvent.InvokeAsync(new ConnectedEventArgs(uri));

    _ws = ws;
    IsRunning = true;

    return Unit.Default;
}

关于无法访问result.Exception的原因

LanguageExt把Result<T>的Exception设为内部属性,是为了强制开发者使用它提供的函数式API(比如Match、IfFail系列方法)来处理结果,避免直接操作内部状态,这是函数式编程强调“纯操作”、避免副作用的设计思路。


内容的提问来源于stack exchange,提问作者Hulkstance

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 04:50:23