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

发布于 2024-09-17 15:11:45 字数 565 浏览 4 评论 0原文

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

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.ObjectDisposeException,您不应在一个对象上多次调用 Dispose。

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

I have an object that uses some underlying native resources, and has a pointer to the next instance, which I iterate through similar to:

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();
    }
}

I get the code analysis problem:

CA2202: Microsoft.Usage: Object 'begin' can be disposed more than once in method 'x()'. To avoid generating a System.ObjectDisposedException you should not call Dispose more than one time on an object.

Any idea how I can get rid of this error without suppressing it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

深巷少女 2024-09-24 15:13:18

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

在最初调用 dispose 的代码中怎么样:

GetFirst().Dispose();

那么 dispose 方法的唯一责任是处置当前项及其子项:

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

这消除了在 dispose 方法中循环的任何需要。我还会看一下 处置模式

You obviously have some mechanism for identifying the first item in the chain, perhaps some other object or some static that is storing the first item?

How about in your code that is originally calling dispose:

GetFirst().Dispose();

Then the only responsibility for the dispose method is to dispose the current item and it's children:

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

This eliminates any need to loop within the dispose method. I would also take a look at the dispose pattern

懒的傷心 2024-09-24 15:13:03

代码分析似乎认为在 Dispose() 方法期间可能会发生异常。如果是这种情况,您将输入带有对 begin 的已处置但非空引用的finally 块。

请注意,如果您计划将对 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;
    }
}

It appears that Code Analysis considers it possible for an exception to occur during the Dispose() method. Were that to be the case, you would enter the finally block with an already-disposed-albeit-non-null reference to begin.

Note that I would only prefer this approach to @Dan's if you plan to wrap the call to begin.Dispose() in additional error trapping and handling. IMO, Dan's solution is more elegant.

Here is a try-finally approach that removes the warning:

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

while (begin != null)
{
    try
    {
        next = begin.Next();
        // do something with begin
    }
    finally
    {
        begin.Dispose();
        begin = next;
    }
}
酒解孤独 2024-09-24 15:12:47

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

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

MyObject begin = GetFirst();

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

    begin = next;
}

请注意,在上面的建议中,实际上仍然可能会出现未处理的对象:在 using 结束之前分配给 next 的最后一个值> 阻止。您原来的问题中没有涵盖这种情况,因此我没有在上述建议中解决它。不过,如果这是一个潜在的问题,那就值得考虑。

It certainly seems to me that your last block of code is unnecessary. If begin != null, then your while loop should have continued, no?

UPDATE: It looks like you're trying to ensure the last obtained value for begin is disposed in case an exception is thrown. Try this:

MyObject begin = GetFirst();

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

    begin = next;
}

Note that in the above suggestion, it could actually still happen that you end up with an undisposed object: the last value assigned to next, before the end of the using block. This scenario wasn't covered in your original question, so I haven't addressed it in the above suggestion. It's something to consider, though, if that's a potential problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文