【问题标题】:Disposing the members that implement IDisposable处置实现 IDisposable 的成员
【发布时间】:2011-03-02 15:32:03
【问题描述】:

在我的 Dispose 方法(如下所示)中,每次我想调用 someObj.Dispose() 时,我也会检查 someObj!=null。

那是因为我的设计不好吗? 他们是否是一种更简洁的方法来确定调用对象中使用的所有成员(实现 IDisposable)的 Dispose 而不存在 NullReference 异常的风险?

protected void Dispose(bool disposing)
        {
            if (disposing)
            {
               if (_splitTradePopupManager != null)
                {
                    _splitTradePopupManager.Dispose();
                }
             }
        }

感谢您的关注。

【问题讨论】:

    标签: c# idisposable nullreferenceexception


    【解决方案1】:

    我喜欢@Dan Tao的解决方案,但它作为扩展方法要好得多,imo:

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

    现在您可以在程序中的任何IDisposable 上调用member.SafeDispose() 而无需担心。 :)

    【讨论】:

    • 在调用扩展方法时不会抛出空引用异常?编辑——我写了一个快速测试应用,效果很好!
    • 不,不会。我在一个项目中使用了类似的方法(DisposeIfNotNull())。
    • 不!由于点运算符只是静态方法的语法糖,所以它工作得很好。 :)
    • 这是我最喜欢的扩展方法之一。不幸的是,在我当前的项目中,我们正在开发 2.0,因此无法选择扩展方法。
    【解决方案2】:

    也许其他人可以插话,但我个人认为这不是设计缺陷——这是最安全的做法。

    也就是说,没有什么能阻止您以方便的方法包装您的 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() 模式可能会在检查和处理之间将_field 设置为null 时导致NullReferenceException(很少见,但可能)。将_field 作为参数传递给诸如DisposeMember 之类的方法会复制对方法中局部变量的引用,从而消除了这种可能性,尽管这种可能性不大。

    【讨论】:

    • 同意这不是设计缺陷。也许我过于谨慎了,但我更喜欢进行空检查,即使我确实知道在一次性用品方面该对象永远不会为空。
    • @ccomet: +1,在对对象调用 Dispose() 时,我有同样的想法(过于谨慎)。
    【解决方案3】:

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

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

    (当然,作为一般规则,引用类型或可空值类型总是可能为空,因此始终包含这些空检查可能是一种好习惯。)

    【讨论】:

      【解决方案4】:

      我能想到的唯一其他选择是创建一个DisposeParameter 辅助方法,它有一个对象作为它的参数,并且只检查它是否为空,否则处置它。这样你只需要一行代码来处理它,但我不确定它是否会使其更具可读性。

      【讨论】:

        【解决方案5】:

        试试这个。

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

        【讨论】:

        • 我不确定我是否理解您在这里的建议。
        • 不是我,但检查成员是否为IDisposable 有点傻,因为当member 不是一次性类型时,对member.Dispose() 的调用将无法编译。
        • stackoverflow.com/questions/2349378/…我没有投反对票,但 null != member 刚刚在那个帖子上提醒了我 ;)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-10-29
        • 2015-10-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-08
        • 2018-12-30
        相关资源
        最近更新 更多