解析代码分析& CA2000"规则在这个场景中

本文关键字:代码 CA2000 quot 规则 | 更新日期: 2023-09-27 18:04:17

我正在对我的项目进行完整的代码分析,它说它有500个问题。我现在已经把它压缩到300了,但是我遇到了一个问题,我似乎找不到解决方案。

规则CA2000规定:

如果一个一次性对象没有在对它的所有引用都超出作用域之前显式地被处置,那么当垃圾收集器运行该对象的终结器时,该对象将在某个不确定的时间被处置。因为可能会发生异常事件,从而阻止对象的终结器运行,因此应该显式地处置对象。

关于该规则的更多信息可以在上面链接的页面找到。

规则失败的代码如下:

internal Window(Game game, Control parent, string title, bool visible)
    : base(game, parent, visible, new ScreenspaceRectangle(game, Color.Black, Vector.Zero, Vector.Zero))
{
}

描述为:

CA2000: Microsoft。可靠性:在Window方法中。Window(Game, Control, string, bool)', call System.IDisposable.Dispose on object ', new ScreenspaceRectangle(Game, Color, Color)。黑色,向量。0, Vector.Zero)',然后对它的所有引用都超出了作用域。

我理解这个问题通常可以通过在正在创建的对象周围使用"using"语句来解决,以确保它总是被正确地处理。但在这种情况下我怎么解呢?

解析代码分析& CA2000"规则在这个场景中

假设Window类是您的自定义类,您应该确保基类构造函数存储了ScreenspaceRectangle的引用,如果它需要在构造函数之外,并且它实现了IDisposable并在Dispose方法中处置了ScreenspaceRectangle的实例。

否则,确保对象在基类构造函数中被处置。

c#/vb.net的一个令人讨厌的限制是,它们不允许将链式构造函数或字段初始化式封装在try-catch或try-finally块中。如果对象Foo的创建需要创建一些其他的IDisposable对象,这些对象将由Foo负责处理,那么如果从Foo的构造函数、其子类型或超类型抛出异常,则很难确保这些对象将被处理。我所知道的最干净的处理方法是使用一个受保护的构造函数,包装在工厂方法中,它将创建一个"可处置的管理器"实例,并将其传递给构造函数链。任何可以创建一次性物品的东西都应该将其添加到一次性物品管理器中;如果构造函数抛出异常,可处置对象管理器将删除所有注册的可处置对象。

这种方法的一个优点是,它允许由创建它们的代码来处理嵌套的IDisposables的清理,从而最小化对象创建和清理代码不同步的危险。需要注意的是,必须使用线程静态字段来跟踪disposables管理器,或者将其传递到构造函数链的每一步。前一种方法感觉有点恶心,但它的优点是允许字段初始化器安全地创建可丢弃的对象。