为什么VS2005 / VB.NET使用Dispose(布局为布尔型)重载实现IDisposable接口? [英] Why does VS2005/VB.NET implement the IDisposable interface with a Dispose(disposing as boolean) overload?

查看:656
本文介绍了为什么VS2005 / VB.NET使用Dispose(布局为布尔型)重载实现IDisposable接口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近我需要用VS2005 / VB.NET提供的自动生成的对象来比较IDisposable和object finalization的建议模式。我们使用自动生成的一个公平的一点,但是看了两个并列后,我有一些有关VB.NET实现的问题...



为了参考,这里是IDE的实现:

 公共类Class1 
实现IDisposable

PrivatewhereValue As Boolean = False''//检测冗余调用

''// IDisposable
受保护的可覆盖子处理(ByVal处置为布尔值)
如果不是我。然后
如果处理然后
''// TODO:明确称为
时的免费托管资源如果

''// TODO:免费共享非托管资源
End If
Me.disposedValue = True
End Sub

#RegionIDisposable Support
''// Visual Basic添加的代码正确实现一次性模式。
Public Sub Dispose()实现IDisposable.Dispose
''不要更改此代码。把清理代码放在上面的Dispose(ByVal disposal As Boolean)中。
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End区域

结束类

问题:


  1. 如果调用Finalize在GC中没有object.Dispose()被明确调用,然后处理:= false,并且如果处理...中的代码永远不会执行,以释放托管资源 - 导致它们保留在内存中,直到下一个GC通过。为什么这些不被明确释放?在第一个GC通行证中不会这样释放更多的内存,而不会在内存中留下不需要的对象,直到下一次通过?

  2. 为什么IDE不会生成Dispose(false)调用覆盖一个IDisposable类的Finalize()?

  3. GC如何知道调用Dispose(false)并确保它是IDE的实现,而不是使用bool参数的自定义实现不同的方式?
    * ...并且如果GC测试其存在并以假定某个实现的方式(object.Dispose(disposal:= false))使用它,则不应该将Dispose(作为bool)处理为接口成员) )?
    *存在 Dispose() Dispose(布置为布尔值)为什么GC有没有选择调用过载的非接口成员?

总体来说,我感到困惑的是,显式地调用 Dispose()时执行的路径,而不是执行一个公共路径,而不管 Dispose()被明确调用)。虽然我可以理解,它提供了良好的意图,我不能看到它如何执行任何其他事情,除了延迟管理资源的实际发布,如果 Dispose()不被称为直。实际上,似乎只能使对象图中的管理资源无法访问,直到第二个GC运行,而不是在已知不再需要它们的时候释放它们。

解决方案

您的问题有一个逻辑错误...如果 Dispose()在Finalizer中调用,那么是的,whereValue 将为false,这意味着 If Not Me.disposedValue Then ... 将执行。 处理的参数是 true ,所以所有代码都应该执行得很好。



修改
(显示Finalizer调用Dispose(false))



表单上的Finalizer(仅在 Dispose()运行时才会在Form中调用)调用 Dispose(false) 。这样做的原因是, Form 目前正在GC。因此,管理资源(即 Form 中的组件)将被收集,并且自己的Finalizer应该调用 Dispose()如果需要。只有非托管资源应在 Dispose(false)中发布。


Recently I needed to compare a suggested pattern for IDisposable and object finalization with the auto-generated one we which VS2005/VB.NET provide. We have used the auto-generated one a fair bit, but after looking it the two side by side I had a number of questions about the VB.NET implementation...

For reference, here is the IDE's implementation:

Public Class Class1
    Implements IDisposable

    Private disposedValue As Boolean = False        ''// To detect redundant calls

    ''// IDisposable
    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If Not Me.disposedValue Then
            If disposing Then
                ''// TODO: free managed resources when explicitly called
            End If

            ''// TODO: free shared unmanaged resources
        End If
        Me.disposedValue = True
    End Sub

#Region " IDisposable Support "
    ''// This code added by Visual Basic to correctly implement the disposable pattern.
    Public Sub Dispose() Implements IDisposable.Dispose
        ''// Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
#End Region

End Class

Questions:

  1. If Finalize() is called during GC without object.Dispose() being explicitly called first then disposing:=false and the code within "if disposing..." will never execute to free the managed resources--resulting in them remaining in memory until the next GC pass. Why wouldn't these be explicitly freed? Wouldn't doing so free more memory on the first GC pass and not leave unneeded objects in memory until the next pass?
  2. Why doesn't the IDE generate the Dispose(false) call when overriding Finalize() on an IDisposable class?
  3. How would the GC know to call Dispose(false) and ensure that it is the IDE's implementation and not a custom implementation which uses the bool parameter in a different manner? * ...and shouldn't Dispose(disposing as bool) be an interface member if the GC tests for its existence and uses it in a manner that assumes a certain implementation (object.Dispose(disposing:=false))? * In the presence of both Dispose() and Dispose(disposing as boolean) why would the GC ever opt to call the overloaded, non-interface member?

Overall I am confused by the supposed added value of having an extended code-path that executes when Dispose() is called explicitly(as opposed to having a common path that is executed regardless of whether or not Dispose() was called explicitly). While I can appreciate that it is provided with good intentions I can't see how it does anything other than delay the actual release of managed resources if Dispose() isn't called directly. In essence it seems to only work to make the managed resources unreachable in the object graph, orphaning them until the 2nd GC run rather than freeing them at a point where they are known to be no longer needed.

解决方案

Your question has a logical error...if Dispose() is called within the Finalizer, then yes, disposedValue will be false, which means that If Not Me.disposedValue Then... will execute. The parameter passed for disposing is true, so all of the code within there should execute just fine.

Edit (turns out the Finalizer calls Dispose(false))

The Finalizer on the form (which only runs if Dispose() is never called on the Form) invokes Dispose(false). The reason for this is that the Form is currently being GC'ed. As a result, MANAGED resources (ie, components on the Form) will get collected and their own Finalizers should invoke Dispose() if required. Only unmanaged resources should be released in Dispose(false).

这篇关于为什么VS2005 / VB.NET使用Dispose(布局为布尔型)重载实现IDisposable接口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆