gpt4 book ai didi

c# - IDisposable 在方法中创建并返回

转载 作者:可可西里 更新时间:2023-11-01 07:55:08 26 4
gpt4 key购买 nike

我很高兴编写了一个运行良好且在运行时不会出现任何异常的项目。所以我决定运行静态代码分析工具(我使用的是 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。我用谷歌搜索过,我用过 msdn'ed,我用过 stackoverflow'ed。找到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以及大量类似的问题。

有什么我遗漏的吗?规则是否有问题/无关紧要?我应该怎么办?忽视?以某种神奇的方式处理?也许应用一些设计模式?

编辑:

在 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 测试

编辑2:

以下方法解决了 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。

最佳答案

这是误报警告。如果 IFoo 实现了 IDisposable,则没有办法返回 IFoo 的适当实例,而代码分析工具没有警告您您没有妥善处理。

代码分析不会分析您的意图或逻辑,它只是尝试对常见错误发出警告。在这种情况下,您“看起来”正在使用 IDisposable 对象而不是调用 Dispose()。在这里,您是按设计来做的,因为您希望您的方法返回一个新实例并将其作为工厂方法的一种形式。

关于c# - IDisposable 在方法中创建并返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14492003/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com