为什么Roslyn的 CA1001不会对自动实现属性的后备字段触发?

编程语言 2026-07-09

这会触发 CA1001: Types that own disposable fields should be disposable

public class MyService1 {
    public System.IO.MemoryStream DataStream = new();
}

但这不会触发:

public class MyService2
{
    public System.IO.MemoryStream DataStream { get; } = new();
}

然而,MyService2 不也有与 MyService1 相同的问题吗?因为它的后备字段包含一个 DataStream,它是 IDisposable?为什么Roslyn不会给出警告?在这种情况下是否可以设置让其给出警告?

解决方案

这并不是一个完整的答案,但基本原因是这个分析器就是这么设计的。

首先,诊断本身 只提到字段,而不是属性:

一个类声明并实现了一个实例字段,该字段是一个 System.IDisposable 类型,且该类没有实现 IDisposable

到底设计团队为什么只把字段作为考虑对象——这个问题有点偏题(是否容易添加自动属性的支持——也可以说是可以做到的)。

当前它只处理字段,而且仅限于通过 new 初始化的字段(目标类型是否显式指定)。例如,下面的代码也不会报告诊断(可能这可以用规则描述中的那段“如果类没有直接拥有任何未托管资源,则不应实现终结器”的说明来解释,但不确定):

public class MyService2 {
    public System.IO.MemoryStream DataStream = Get();
    public static System.IO.MemoryStream Get() => new();
}

TypesThatOwnDisposableFieldsShouldBeDisposable 据我所知负责这个诊断的搜索仅针对字段声明:

var disposableFields = namedType
    .GetMembers()
    .OfType<IFieldSymbol>()
    .Where(f => !f.IsStatic && disposeAnalysisHelper.IsDisposable(f.Type))
    .ToSet();

由于没有被声明的字段,因此这里没有可报告的内容。

另外请注意,分析很可能是在实际的后备字段生成/输出之前进行的——参见我对 为什么在Rider中以Release模式编译时后缀运算符 ! 被认为不需要的原因 的一些分析/猜测。因此简而言之,答案是——分析器只对开发人员实际编写的代码起作用,而不对将要生成的代码起作用(这方面可能有像 Infer# 这类工具可以在这个层面工作,但对于这类任务来说会显得太过庞大)。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章