释放实现IDisposable的成员

9
在我的Dispose方法中(如下所示),每次我想调用someObj.Dispose()时,我也会检查someObj!= null。
这是因为我的设计有问题吗?有没有更清晰的方法来确定在调用对象中使用的所有成员(实现IDisposable)的Dispose时,不会有NullReference异常的风险?
protected void Dispose(bool disposing)
        {
            if (disposing)
            {
               if (_splitTradePopupManager != null)
                {
                    _splitTradePopupManager.Dispose();
                }
             }
        }

感谢您的关注。
5个回答

10

我喜欢@Dan Tao的解决方案,但我认为将其作为扩展方法会更好:

public static void SafeDispose(this IDisposable obj)
{
    if (obj != null)
        obj.Dispose();
}

现在你可以在程序中调用任何IDisposablemember.SafeDispose()而不必担心了。 :)


当它尝试调用扩展方法时,那不会抛出空引用异常吗?编辑 - 我编写了一个快速测试应用程序,它运行得很好! - Scott Chamberlain
不,不会。我在一个项目中使用了类似的方法(DisposeIfNotNull())。 - Eric Olsson
2
不需要!由于点运算符只是静态方法的语法糖,所以它可以正常工作。 :) - tzaman
这是我最喜欢的扩展方法之一。不幸的是,在我的当前项目中,我们正在使用2.0版本,无法使用扩展方法。 - Manish Basantani

5
也许其他人可以对此发表意见,但我个人认为这不是设计缺陷 - 只是最安全的方法。
话虽如此,没有什么可以阻止您将null检查和Dispose调用包装在一个方便的方法中:
private void DisposeMember(IDisposable member)
{
    if (member != null)
        member.Dispose();
}

那么您的 Dispose 方法就可以看起来更加简洁一些:
protected void Dispose(bool disposing)
{
    if (disposing)
    {
        DisposeMember(_splitTradePopupManager);
        DisposeMember(_disposableMember2);
        DisposeMember(_disposableMember3);
    }
}

作为额外的奖励,这也解决了原始代码中可能存在的竞态条件。如果在多线程上下文中运行,则 if (_field != null) _field.Dispose() 模式可能会导致 NullReferenceException,当 _field 在检查和处置之间被设置为 null 时(虽然罕见,但是可能发生)。将 _field 作为参数传递给诸如 DisposeMember 的方法将引用复制到方法中的本地变量中,消除了这种可能性,尽管可能性很小。

1
同意它不是设计缺陷。也许我过于谨慎了,但即使在处理可释放对象时我可以确定该对象永远不会为空,我仍然更喜欢进行空值检查。 - Grace Note
@ccomet:+1,我有同样的想法(过度谨慎),在调用对象的Dispose()方法时会在脑海后面思考。 - Manish Basantani

0

只有你知道这个问题的答案!

如果没有看到整个类,其他人很难判断在调用Dispose时,那些成员是否可能为空。

当然,通常情况下,引用类型或可空值类型可能为空,因此最好始终包含这些null检查,这是一个很好的习惯。


0

我能想到的另一个选项是创建一个DisposeParameter帮助方法,该方法有一个对象作为它的参数,并仅检查它是否为null,否则就Dispose掉它。这样你只需要一行代码来处理它,但我不确定它是否会让代码更易读。


-1

试试这个。

    protected void Dispose(bool disposing) 
    { 
        if (disposing) 
        {
           //for all members.. 
           if (null != member && member is IDisposible) 
            { 
                member.Dispose(); 
            } 
         } 
    } 

我不确定我理解你在这里提出的建议。 - Dan Tao
4
这不是我的错,但检查成员是否为“IDisposable”有点愚蠢,因为当“member”不是可处理类型时,对“member.Dispose()”的调用将无法编译。 - Steven
http://stackoverflow.com/questions/2349378/new-programming-jargon-you-coined/2430307#2430307 顺便说一句,我没有给你点踩,但是 null != member 只是让我想起了那个帖子 ;) - Jürgen Steinblock

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接