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

C#开发Discord机器人检测游戏分配角色空引用错误如何修复

问题原因

当用户退出所有游戏后,SocketGuildUser.Activity 属性会返回null,你通过as Game转换后得到的Game变量为null,后续直接访问Game.Name就会触发NullReferenceException空引用异常。
除此之外原代码还有多处可优化的冗余逻辑:

  • 已经拿到事件参数after(更新后的用户实例),不需要重复调用GetGuild、GetUser拉取用户数据
  • 先做Activity读取操作再判断用户是否为Bot,无效操作多
  • 没有判断用户是否已经持有目标身份组,重复调用Add/Remove接口容易触发Discord限流
  • 没有利用before参数过滤非活动状态变更的事件,所有用户信息变更(改昵称、改头像等)都会触发逻辑,浪费性能

修复后代码

private async Task UserUpdated(SocketGuildUser before, SocketGuildUser after)
{
    // 先过滤机器人,提前返回减少无效操作
    if (after.IsBot) return;
    // 先获取目标角色,建议把myguildid、myroleid做成全局只读常量
    var targetGuild = after.Guild;
    var targetRole = targetGuild.GetRole(myroleid);
    if (targetRole == null) return; // 角色不存在直接返回避免后续报错
    // 只有活动状态变化才处理,过滤其他用户信息变更事件
    if (before?.Activity?.Name == after?.Activity?.Name) return;
    // 判断当前是否在玩指定游戏,一次性完成类型判断+空值检查
    bool isPlayingTargetGame = after.Activity is Game game && game.Name.Equals("mygamename", StringComparison.OrdinalIgnoreCase);
    // 检查用户当前是否持有目标角色,避免重复调用接口
    bool hasTargetRole = after.Roles.Any(r => r.Id == myroleid);

    if (isPlayingTargetGame && !hasTargetRole)
    {
        await after.AddRoleAsync(targetRole);
    }
    else if (!isPlayingTargetGame && hasTargetRole)
    {
        await after.RemoveRoleAsync(targetRole);
    }
}

优化说明

  • 用is Game game语法一次性完成类型判断+空值判断+变量声明,从根源避免空引用异常
  • 利用before参数对比活动状态,只有活动变化时才执行后续逻辑,大幅减少无效执行次数
  • 增加角色存在性、用户角色持有状态判断,避免无效API调用,降低触发Discord接口限流的概率
  • 字符串比对用StringComparison.OrdinalIgnoreCase忽略大小写,避免游戏名称大小写不一致导致匹配失败

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 01:54:04