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

Discord.NET:如何识别命令执行抛出的具体异常类型

解决CommandService无法识别自定义异常的问题

我之前做机器人命令系统的时候也碰到过一模一样的问题——自定义了权限不足、冷却触发这类业务异常,但CommandService.ExecuteAsync()返回的Error只会显示CommandError.Exception,没法直接区分具体异常类型。其实核心解决思路很简单,就是从执行结果的Exception属性里捞到你抛出的原始自定义异常就行。

核心方案:捕获并识别原始异常

大部分CommandService的实现会把执行过程中抛出的异常包装在返回的CommandResult对象的Exception属性里,而非直接向外抛出(除非是致命未处理错误)。所以不用在外层套try-catch,而是检查执行结果的成功状态,再针对性判断异常类型:

步骤1:给自定义异常统一基类(可选但推荐)

先给你的业务异常定义一个公共基类,后续判断起来更简洁,避免一堆零散的if-else:

// 自定义命令异常基类
public abstract class CommandBusinessException : Exception
{
    // 给用户展示的友好提示
    public abstract string UserTip { get; }
}

// 无权限异常
public class NoPermissionException : CommandBusinessException
{
    public override string UserTip => "抱歉,你没有执行这个命令的权限哦";
}

// 冷却触发异常
public class CommandCooldownException : CommandBusinessException
{
    public TimeSpan RemainingTime { get; }

    public CommandCooldownException(TimeSpan remaining)
    {
        RemainingTime = remaining;
    }

    public override string UserTip => $"命令还在冷却中,还剩 {RemainingTime:mm\\:ss} 才能再次使用";
}

步骤2:执行后判断具体异常类型

执行命令后,先检查结果是否成功,如果失败,就从result.Exception中提取真实的自定义异常(注意部分库会把异常包装在AggregateException里,需要取内层异常或者用GetBaseException()获取最原始的异常):

var result = await _service.ExecuteAsync(context);

if (!result.IsSuccess)
{
    // 获取最内层的原始异常
    var actualException = result.Exception.GetBaseException();

    // 用switch判断异常类型,逻辑更清晰
    switch (actualException)
    {
        case NoPermissionException noPermEx:
            await context.Channel.SendMessageAsync(noPermEx.UserTip);
            break;
        case CommandCooldownException cooldownEx:
            await context.Channel.SendMessageAsync(cooldownEx.UserTip);
            break;
        default:
            // 处理其他未知异常
            await context.Channel.SendMessageAsync("执行命令时发生了未知错误,请稍后再试");
            // 这里可以记录异常日志
            _logger.LogError(actualException, "命令执行失败");
            break;
    }
}

额外提醒

  • 如果你的CommandService在极端情况下会直接抛出异常,外层的try-catch还是需要保留,但大部分场景下异常都会被包装在CommandResult里。
  • 尽量避免直接捕获Exception类型,优先判断自定义异常基类,这样不会把数据库连接错误这类非业务异常当成命令逻辑问题处理。

这样你就能继续用自定义异常统一处理权限、冷却这些场景,不用重复写判断逻辑,同时也能准确识别不同的异常类型了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:53:46