如何处理通过Next属性迭代的对象?

时间:2010-09-01 23:30:11

标签: c# code-analysis ca2202

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

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:对象'begin'可以在方法'x()'中多次处理。为避免生成System.ObjectDisposedException,不应在对象上多次调用Dispose。

任何想法如何在不压制它的情况下摆脱这个错误?

3 个答案:

答案 0 :(得分: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的最后一个值。您的原始问题未涵盖此方案,因此我未在上述建议中解决此问题。但是,如果这是一个潜在的问题,这是值得考虑的事情。

答案 1 :(得分:0)

似乎Code Analysis认为在Dispose()方法期间可能发生异常。如果是这种情况,您将输入finally块,其中包含对begin已经处理过的非空引用。

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

这是一个尝试 - 终止方法,删除警告:

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

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

答案 2 :(得分:0)

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

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

GetFirst().Dispose();

然后处置方法的唯一责任是处理当前项目及其子项:

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

这消除了在dispose方法中循环的任何需要。我还要看一下dispose pattern