开发者

Resolving code analysis "CA2000" rule in this scenario?

开发者 https://www.devze.com 2023-03-23 21:39 出处:网络
I\'m running a full code analysis on my project, and it says it has 500 issues. I\'ve boiled it down to 300 now, but I\'m struggling with an issue I can\'t seem to find a solution for.

I'm running a full code analysis on my project, and it says it has 500 issues. I've boiled it down to 300 now, but I'm struggling with an issue I can't seem to find a solution for.

The rule CA2000 states:

If a disposable object is not explicitly disposed before all referenc开发者_Go百科es to it are out of scope, the object will be disposed at some indeterminate time when the garbage collector runs the finalizer of the object. Because an exceptional event might occur that will prevent the finalizer of the object from running, the object should be explicitly disposed instead.

More information on the rule can be found on the page linked to above.

The code that the rule is failing on is this:

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

And the description is:

CA2000 : Microsoft.Reliability : In method 'Window.Window(Game, Control, string, bool)', call System.IDisposable.Dispose on object 'new ScreenspaceRectangle(game, Color.Black, Vector.Zero, Vector.Zero)' before all references to it are out of scope.

I understand that this issue can be resolved normally by using a "using" statement around the object being created, to make sure that it is always properly disposed. But how do I solve it in this case?


Assuming that the Window class is your custom class, you should ensure that the base class constructor is storing the reference of ScreenspaceRectangle if it requires it outside the constructor and it implements IDisposable and disposes the instance of ScreenspaceRectangle in the Dispose method.

Otherwise ensure that the object is being disposed in the base class constructor.


One annoying limitation of c#/vb.net is that they don't allow chained constructors or field initializers to be wrapped in a try-catch or try-finally block. If the creation of object Foo requires the creation of some other IDisposable objects which Foo will be responsible for disposing, it can be difficult to ensure that those objects will get disposed if an exception is thrown from the constructor of Foo, its subtype, or its supertype. The cleanest way I know of to deal with this is to use a protected constructor, wrapped in factory methods that will create a "disposables manager" instance and pass it through the constructor chain. Anything that would create an IDisposable should add it to the disposables manager; if the constructor throws an exception, the disposables manager will delete all registered disposables.

One advantage of this approach is that it allows the cleanup of nested IDisposables to be handled by the code that creates them, thus minimizing the danger of object-creation and cleanup code getting out of sync. One caveat is that one must either use a thread-static field to keep track of the disposables manager, or else pass it through every step of the constructor chain. The former approach feels icky, but has the advantage of allowing field initializers to safely create IDisposable objects.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号