解决此方案中的代码分析“CA2000”规则?

时间:2011-07-31 06:45:22

标签: c# .net code-analysis idisposable

我正在对我的项目运行完整的代码分析,它说它有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.Reliability:在方法'Window.Window(Game,Control,string,bool)'中,在对象'new ScreenspaceRectangle(游戏,Color.Black,Vector.Zero,Vector)上调用System.IDisposable.Dispose。在所有对它的引用超出范围之前'零)。

我知道通过在正在创建的对象周围使用“using”语句可以正常解决此问题,以确保始终正确处理它。但是在这种情况下如何解决呢?

2 个答案:

答案 0 :(得分:3)

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

否则,请确保将对象放置在基类构造函数中。

答案 1 :(得分:1)

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

这种方法的一个优点是它允许嵌套IDisposable的清理由创建它们的代码处理,从而最大限度地降低了对象创建和清理代码不同步的危险。需要注意的是,必须使用线程静态字段来跟踪一次性管理器,或者将其传递给构造函数链的每一步。前一种方法感觉很蹩脚,但具有允许字段初始化器安全地创建IDisposable对象的优势。