最近,我需要将 IDisposable 和对象终结的建议模式与 VS2005/VB.NET 提供的自动生成模式进行比较。我们已经使用了自动生成的一个,但是在并排查看它之后,我对 VB.NET 实现有很多疑问......
作为参考,这里是 IDE 的实现:
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
问题:
- 如果在 GC 期间调用 Finalize() 而没有首先显式调用 object.Dispose() 则 disposing:=false 并且“if disposing...”中的代码将永远不会执行以释放托管资源 - 导致它们保留在内存中直到下一次GC通过。为什么不明确释放这些?这样做不会在第一次 GC 传递时释放更多内存,并且不会在下一次传递之前将不需要的对象留在内存中吗?
- 为什么在 IDisposable 类上覆盖 Finalize() 时 IDE 不生成 Dispose(false) 调用?
- GC 如何知道调用 Dispose(false) 并确保它是 IDE 的实现,而不是以不同方式使用 bool 参数的自定义实现?* ...如果 GC 测试它的存在并以假定某个实现的方式使用它(object.Dispose(disposing:=false)),那么 Dispose(disposing as bool) 不应该是接口成员吗?* 在两者都存在的情况下
Dispose()
,Dispose(disposing as boolean)
为什么 GC 会选择调用重载的非接口成员?
总体而言,我对具有在显式调用时执行的扩展代码路径的假定附加值感到困惑Dispose()
(与具有无论是否Dispose()
显式调用都执行的公共路径相反)。虽然我可以理解它是出于善意提供的,但如果Dispose()
不直接调用它,除了延迟托管资源的实际释放之外,我看不到它是如何做的。从本质上讲,它似乎只能使对象图中的托管资源无法访问,将它们孤立起来直到第二次 GC 运行,而不是在已知不再需要它们的时候释放它们。