【问题标题】:Why is there no compiler or analyzer warning when an IDisposable object is not disposed within a method?当 IDisposable 对象未在方法中释放时,为什么没有编译器或分析器警告?
【发布时间】:2022-06-28 00:47:27
【问题描述】:

示例代码:

internal class Program
{
    static void Main(string[] args)
    {
        Foo foo = new Foo();
    }
}

public class Foo : IDisposable
{
    public void Dispose()
    {
        // Not invoked.
        Console.WriteLine("Foo disposed");
    }
}

这里的 Foo 类型是 IDisposable,但 'foo' 变量没有包含在 'Using' 语句中;具有“使用”块/范围的传统语法,或者当变量超出范围时调用 Dispose() 的新语法,如下所示:

using Foo foo = new Foo();

鉴于这可能是资源泄漏的来源,为什么没有针对这种情况的编译器警告或分析器规则?

我询问是因为这似乎是一件显而易见的事情,因此我怀疑这个遗漏是有充分理由的;如果是这样,我想知道为什么。

谢谢。

【问题讨论】:

  • 你的意思是CA2000?配置和启用分析器的方式因 .NET 版本而异,但这是最古老和最古老的规则之一。
  • 谢谢。我会看,但默认情况下它似乎被禁用(?)。 IE。具有上述代码的新空项目不会报告此警告。
  • 我只能推测,但似乎有很多方法可以在编译器没有真正注意到的情况下使其安全。首先,using 的两种风格都只是语法糖;您也可以手动拨打Dispose()。然后,一些类提供内部调用Dispose() 的方法(例如一些I/O 类的Close() 方法)。然后,一次性类的 ctor可以在应用程序退出事件上注册自己,例如,以确保它被清理。最终,某些类(如MemoryStream)继承IDisposable,但实际上可以安全使用,无需...
  • @O.R.Mapper 我认为您提出的那些场景将是默认启用此规则并在您不想要它时依赖规则抑制的良好候选者。但是,是的,感谢您对此的想法。有趣的是,对象上 Disposable /fields/ 的规则对于 Stream 和其他类有特殊情况docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/…
  • @redcalx:是的,根据文档,其中一些情况被列为“何时禁止警告”。也许随着时间的推移,MS意识到特殊情况变得太多了?正如我所说,我只能在这里推测;不过,如果在接下来的几天内没有其他答案出现,我可能仍会将上述内容作为答案发布。

标签: c# idisposable


【解决方案1】:

我很确定这是因为您并不总是想要Dispose 对象。

在这个过于简单的示例中,该方法创建了一个StreamWriter 以将一些字符串数据附加到StreamStream 可能是 NetworkStreamFileStream 或其他...不处置 StreamWriter 实际上是您想要的,因为如果您执行了底层 Stream 也将被处置(因此 IO 连接将关闭)。

void AppendWhateverToStream(Stream stream)
{
    StreamWriter writer = new(stream);

    writer.WriteLine("whatever");
}

此外,如果你的类有非托管资源无论如何都需要处理,那么它应该通过使用终结器来实现Dispose Pattern,而不是依赖于不会忘记写using的人。

【讨论】:

    猜你喜欢
    • 2012-04-06
    • 2012-10-17
    • 2015-05-29
    • 2020-10-27
    • 1970-01-01
    • 1970-01-01
    • 2020-04-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多