CA2000 passing object reference to base constructor in C#

耗尽温柔 提交于 2019-12-01 03:16:26

If you're using Visual Studio 2010 then CA2000 is completely broken. It may also be broken in other versions of FxCop (a.k.a. Code Analysis), but VS2010 is the only one I can vouch for. Our codebase is giving CA2000 warnings for code like this...

internal static class ConnectionManager 
{
    public static SqlConnection CreateConnection()
    {
         return new SqlConnection("our connection string");
    }
}

...indicating that the connection is not being disposed before it goes out of scope in the method. Well, yeah, that's true, but it isn't out of scope for the application as it's returned to a caller - that's the whole point of the method! In the same way, your constructor argument isn't going out of scope but is being passed to the base class, so it's a false positive from the rule rather than an actual problem.

This used to be a useful rule, but now all you can really do is turn it off until they fix it. Which is unfortunate, because the (very few) actual positives are things that should be fixed.

There is no safe and elegant way to have a chained constructor pass a new IDisposable object to the base constructor, since as you note it's not possible to wrap the chained constructor call in any sort of try finally block. There is an approach which is safe, but it's hardly elegant: define a utility method something like:

internal static TV storeAndReturn<TR,TV>(ref TR dest, TV value) where TV:TR
{ 
  dest = value; return value;
}

Have the constructor look something like:

protected DataGridViewMyCustomColumn(ref IDisposable cleaner) : 
   base(storeAndReturn(ref cleaner, new DataGridViewMyCustomCell()))
{
}

Code which needs a new object would then have to call a public static factory method which would call the appropriate constructor within a try/finally block whose main line would null out cleaner just before it finished, and whose finally block would call Dispose on cleaner if it's not null. Provided that every subclass defines a similar factory method, this approach will ensure that the new IDisposable object will get disposed even if an exception occurs between time it's created and the time the encapsulating object is exposed to client code. The pattern is ugly, but I'm not sure any nicer other pattern would assure correctness.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!