在Blazor中删除类实例后Singleton服务内的引用是否会触发空异常?
关于Blazor服务端Singleton持有实例的回收问题解答
核心结论
你担心的「已传递给其他对象的引用被GC误回收」问题完全不会出现,C#的垃圾回收机制有明确的活跃对象判定规则,和实例的创建来源没有绑定关系。
具体规则说明
- C# GC的判定核心是可达根引用:只要对象还有任意一个处于活跃生命周期的对象持有它的引用,就不会被标记为可回收对象。Singleton服务的生命周期和服务器应用进程完全一致,属于全程活跃的根引用对象,只要你没有主动从Singleton服务中移除对应Player实例的引用,这个实例就会一直保留,不受创建它的原始对象(比如Blazor组件、Scoped服务、会话上下文)释放的影响。
- 你实测中用户离开页面后实例仍被保留是完全符合预期的表现,C#中不存在「创建实例的对象释放就连带销毁所有指向该实例的引用」的逻辑,引用只是指向内存对象的指针,传递引用的操作不会给对象绑定创建者的生命周期。
额外提示:你反而需要警惕该场景的内存泄漏风险:如果玩家离开会话后你不主动从Singleton服务中清理对应的Player实例引用,该实例会一直占用服务器内存,玩家量积累后会出现不必要的资源消耗。
- Blazor本身不会修改C#原生的GC逻辑,Blazor服务端项目的对象回收规则和普通ASP.NET Core项目完全一致。
- 可能触发空引用异常的唯一场景是:你主动从Singleton服务中移除了Player实例、或者将对应引用置为
null之后,仍然尝试访问该引用,GC绝不会主动将仍被持有的引用置为null。
内容的提问来源于stack exchange,提问作者Bennyboy1973
相关产品推荐
相关产品推荐

