我很高兴编写了一个很好的项目,并且在运行时没有任何奇怪之处。因此,我决定运行静态代码分析工具(我使用的是Visual Studio 2010)。结果是违反了规则CA2000
,消息如下:
警告-CA2000:Microsoft.Reliability:在方法'Bar.getDefaultFoo()'中,在对对象'new Foo()'进行调用之前,请对其进行调用System.IDisposable.Dispose。'>
引用的代码如下:
private static IFoo getDefaultFoo() { return (Baz.canIDoIt()) ? new Foo() : null; }
我以为自己:也许条件表达式破坏了逻辑(我的或验证者的逻辑)。更改为:
private static IFoo getDefaultFoo() { IFoo ret = null; if (Baz.canIDoIt()) { retFoo = new Foo(); } return ret; }
再次发生相同的事情,但是现在将该对象称为
retFoo
。我用谷歌搜索,我已经搜索,我已经stackoverflow了。找到this article。创建对象后,无需执行任何操作。我只需要返回对它的引用。但是,我尝试应用OpenPort2示例中建议的模式。现在代码看起来像这样:
private static IFoo getDefaultFoo() { Foo tempFoo = null; Foo retFoo = null; try { if (Baz.canIDoIt()) { tempFoo = new Foo(); } retFoo= tempFoo; tempFoo = null; } finally { if (tempFoo != null) { tempFoo.Dispose(); } } return retFoo; }
再次出现相同的消息,但这次
tempFoo
变量违反了规则。因此,基本上,代码变得扭曲,更长,几乎没有非理性,不必要的复杂性,并且功能完全相同,但速度较慢。
我也发现了this question,其中相同的规则似乎以类似的方式攻击有效的代码。并且建议提问者忽略该警告。我也阅读了this thread和大量类似的问题。
我有什么想念的吗?规则是否错误/无关?我该怎么办?忽视?以某种magickal方式处理?也许应用一些设计模式?
编辑:
在Nicole的请求之后,我以我也尝试使用的形式提交了整个相关代码。
public class DisposableFooTest { public interface IFoo { void bar(); } public class Foo : IFoo, IDisposable { public void bar() { Console.Out.WriteLine("Foo baring now"); } public void Dispose() { // actual Dispose implementation is irrelevant, or maybe it is? // anyway I followed microsoft dispose pattern // with Dispose(bool disposing) } } public static class Baz { private static bool toggle = false; public static bool canIDoIt() { toggle ^= true; return toggle; } } private static IFoo getDefaultFoo() { IFoo result = null; try { if (Baz.canIDoIt()) { result = new Foo(); } return result; } catch { if (result != null) { (result as IDisposable).Dispose(); // IFoo does not inherit from IDisposable, hence the cast } throw; } } public static void Main() { IFoo bar = getDefaultFoo(); } }
分析报告包含以下内容:`CA2000:Microsoft.Reliability:在方法'DisposableFooTest.getDefaultFoo()'中,在对对象'result'的所有引用都超出范围之前,调用System.IDisposable.Dispose。 %% projectpath %% \ DisposableFooTest.cs 44测试
Edit2:
以下方法解决了CA2000问题:
private static IFoo getDefaultFoo() { Foo result = null; try { if (Baz.canIDoIt()) { result = new Foo(); } return result; } finally { if (result != null) { result.Dispose(); } } }
不幸的是,我不能那样走。而且,我希望遵循面向对象的原理,良好实践和准则来简化代码,使其可读性,可维护性和可扩展性。我怀疑有人会按预期阅读它:如果可能,给Foo,否则给null。
我很高兴编写了一个很好的项目,并且在运行时没有任何奇怪之处。因此,我决定运行静态代码分析工具(我使用的是Visual Studio 2010)。结果表明,规则CA2000 ...
这是一个误报。如果IFoo
实现了IFoo
,则无法返回IDisposable
的适当实例,而没有代码分析工具警告您未正确处理它。