2

我有一个使用一些底层本机资源的对象,并且有一个指向下一个实例的指针,我对其进行迭代,类似于:

MyObject begin = null;

try
{
    begin = GetFirst();

    while (begin != null)
    {
        MyObject next = begin.Next();
        // do something with begin
        begin.Dispose();
        begin = next;
    }
}
finally
{    
    if (begin != null)
    {
        begin.Dispose();
    }
}

我得到代码分析问题:

CA2202:Microsoft.Usage:对象“开始”可以在方法“x()”中多次处理。为避免生成 System.ObjectDisposedException,您不应在一个对象上多次调用 Dispose。

知道如何在不抑制它的情况下摆脱这个错误吗?

4

3 回答 3

4

在我看来,您的最后一段代码当然是不必要的。如果begin != null,那么您的while循环应该继续,不是吗?

更新:看起来您正在尝试确保处理最后获得的值begin,以防引发异常。试试这个:

MyObject begin = GetFirst();

while (begin != null)
{
    MyObject next;
    using (begin)
    {
        next = begin.Next();
        // do something with begin
    }

    begin = next;
}

请注意,在上述建议中,实际上仍然可能最终得到一个未处理的对象:next在块结束之前分配给 的最后一个值using。您最初的问题中没有涵盖这种情况,因此我没有在上述建议中解决它。但是,如果这是一个潜在的问题,则需要考虑。

于 2010-09-01T23:33:52.667 回答
0

代码分析似乎认为在该Dispose()方法期间可能会发生异常。如果是这种情况,您将进入 finally 块,其中包含对begin.

begin.Dispose()请注意,如果您打算将调用包装到额外的错误捕获和处理中,我只会更喜欢@Dan 的这种方法。IMO,丹的解决方案更优雅。

这是一种消除警告的 try-finally 方法:

MyObject begin = GetFirst();
MyObject next = null;

while (begin != null)
{
    try
    {
        next = begin.Next();
        // do something with begin
    }
    finally
    {
        begin.Dispose();
        begin = next;
    }
}
于 2010-09-02T00:19:33.433 回答
0

您显然有一些机制来识别链中的第一项,也许是其他一些对象或存储第一项的静态?

在您最初调用 dispose 的代码中如何:

GetFirst().Dispose();

那么 dispose 方法的唯一职责就是处理当前项及其子项:

public void Dispose()
{
    if (Next() != null)
    {
        Next().Dispose();
    }
}

这消除了在 dispose 方法中循环的任何需要。我也会看看dispose 模式

于 2010-09-02T00:28:07.687 回答