VS2010代码分析期间的IDisposable和CA2000警告
我在这里需要一些建议,我希望有人可以帮助我。我有以下类结构(简化):
public class Bar: IDisposable {...}
public abstract class FooBase: IDisposable
{
Bar bar;
bool disposed;
internal FooBase(Bar bar)
{
this.bar=bar;
}
public void Dispose()
{
Dispose(true);
GC.SupressFinalize(this);
}
protected void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
this.bar.Dispose();
}
this.disposed = true;
}
}
}
public FooA: Foo {...}
public FooB: Foo {...}
public static class FooProvider
{
public static FooA GetFooA()
{
Bar bar = new Bar();
...
return new FooA(bar);
}
public static FooB GetFooB()
{
Bar bar = new Bar();
...
return new FooB(bar);
}
...
}
当我对此运行代码分析时,我在 FooProvider 类的所有“CreateFooX()”方法上收到警告 CA2000。此警告提供以下消息:
“Microsoft.Reliability:在方法“FooProvider.GetFooX()”中,在对象“bar”的所有引用超出范围之前调用 System.IDisposable.Dispose。”
微软建议永远不要抑制这个警告,但我不太确定它的警告是关于代码中的真正问题。确实,在我们考虑的任何“CreateFooX()”方法中,“bar”在超出范围之前都不会被释放,但对它的引用存在于“FooX”对象中,该对象最终将被释放,并依次负责释放“酒吧'。
我对 Dispose 模式应该如何工作的理解是否有误,并且我的代码中存在一些根本缺陷,或者我应该抑制此警告?
编辑
由于一些评论,我尝试将工厂方法修改为以下内容:
public static class FooProvider
{
public static FooA GetFooA()
{
Bar bar = null;
try
{
bar = new Bar();
...
return new FooA(bar);
}
catch
{
if (bar != null) bar.Dispose();
throw;
}
}
...
}
但我仍然收到相同的警告。我猜这只是误报,我可以安全地接受它。
感谢您的任何建议。
I need some advice here, I hope somebody can help me. I have the following class structure (simplified):
public class Bar: IDisposable {...}
public abstract class FooBase: IDisposable
{
Bar bar;
bool disposed;
internal FooBase(Bar bar)
{
this.bar=bar;
}
public void Dispose()
{
Dispose(true);
GC.SupressFinalize(this);
}
protected void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
this.bar.Dispose();
}
this.disposed = true;
}
}
}
public FooA: Foo {...}
public FooB: Foo {...}
public static class FooProvider
{
public static FooA GetFooA()
{
Bar bar = new Bar();
...
return new FooA(bar);
}
public static FooB GetFooB()
{
Bar bar = new Bar();
...
return new FooB(bar);
}
...
}
When I run Code Analysis on this, I get Warnings CA2000 on all 'CreateFooX()' methods of the FooProvider class. This warning gives the following message:
"Microsoft. Reliability: In method 'FooProvider.GetFooX()', call System.IDisposable.Dispose on object 'bar' before all references to it are out of scope."
Microsoft recommends to never suppress this warning but I'm not really sure its warning about a real problem in the code. True that 'bar' is not disposed before going out of scope in whatever 'CreateFooX()' method we consider but a reference to it lives on in the 'FooX' object which eventually will get disposed and will in turn take care of disposing 'bar'.
Am I understanding something wrong about how the Dispose pattern should work and I have some fundamental flaw in my code or should I just suppress this warning?
EDIT
Due to some comments I tried modifying the factory methods to the following:
public static class FooProvider
{
public static FooA GetFooA()
{
Bar bar = null;
try
{
bar = new Bar();
...
return new FooA(bar);
}
catch
{
if (bar != null) bar.Dispose();
throw;
}
}
...
}
But I still get the same warning. I guess its just a false positive and I'm safe ingoring it.
Thanks for any advice.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这是代码分析部分的典型误报。它确实无法理解代码的内在情况,因此它会给出一个一般性的答案。请谨慎行事,但每当您确认存在误报时,您都可以安全地忽略它。
This is a typical false positive on Code Analysis' part. It really cannot understand the intrinsic situation of your code, so it throws a general answer at it. Proceed with caution, but whenever you verify that you have a false positive, you can safely ignore it.
这不是误报。如果在创建
Bar
之后但在将其传递给Foo
构造函数之前抛出异常怎么办?我看到几个代码路径,其中一个或多个对象可能无法被处理。That is not a false positive. What if an exception is thrown after the
Bar
is created but before it is passed to theFoo
constructor? I see several code paths where one or more objects might not be disposed of.你的一次性模式对我来说似乎有点不对劲。我认为您不应该在 FooBase 类中调用 bar.Dispose 。为了确保您正在处置的对象的安全并能够安全地多次调用 Dispose,我会推荐这种方法。
至于错误,我认为这应该解决静态分析警告。我在测试项目中实现了您的代码,如下所示,启用了所有静态分析警告,而没有出现警告问题。
我希望这有帮助。
Your disposable pattern seems a little off to me. I don't think you should be calling bar.Dispose in the FooBase class. For safety of the objects you are disposing and being able to safly call Dispose multiple time I would recoment this approach.
As for the error, I think that this should take care of the static analysis warning. I implemented your code as follows in a test project, enabled all static analysis warnings without having an issue with warnings.
I hope this is helpful.
至少这个问题的一部分并不是真正的误报,即使它不一定是一个非常有用的问题检测。要解决编辑版本中的剩余问题,您需要在
bar
赋值之后立即打开try
块,而不是在其之前。 例如:不幸的是,在进行此更改后,您仍然会遇到 CA2000 违规,这可能是误报。这是因为该规则不会检查您是否将
bar
置于新创建的FooA
的状态中。如果它进入FooA
中的状态,您可以安全地创建对违规的抑制。但是,如果它没有进入FooA
中的状态,则应将其放置在finally
子句中,而不是catch
子句中。At least part of this problem isn't really a false positive, even if it's not necessarily a very useful issue detection. To fix the remaining problem your edited version, you need to open the
try
block immediately after thebar
assignment, not before it. e.g.:Unfortunately, after you make this change, you'll still get a CA2000 violation, which will probably be a false positive. That's because the rule doesn't check to see if you're placing
bar
into the state of the newly createdFooA
. If it is going into state in theFooA
, you can safely create a suppression for the violation. However, if it's not going into state inFooA
, you should dispose it in afinally
clause instead of acatch
clause.