1
12
您应该捕获构造函数中的任何异常,然后处理子对象,然后重新引发原始异常(或提供附加信息的新异常)。
|
2
1
对象的构造函数将不负责创建它所拥有的IDisposable对象。相反,工厂将创建每个IDisposable,并调用所有者对象上的构造函数。然后,工厂将owner对象中的适当成员设置为创建的一次性对象。
|
3
1
Public Class RaiiTest Inherits raiiBase(Of String) Dim thing1 As testDisposable = RAII(New testDisposable("Moe " & creationParam, "a")) Dim thing2 As testDisposable = RAII(New testDisposable("Larry " & creationParam, "b")) Dim thing3 As testDisposable = RAII(New testDisposable("Shemp " & creationParam, "c")) Dim thing4 As testDisposable = RAII(New testDisposable("Curly " & creationParam, "d")) Protected Sub New(ByVal dispList As Stack(Of IDisposable), ByVal newName As String) MyBase.New(dispList, newName) End Sub Private Shared Function _newRaiiTest(ByVal dispList As Stack(Of IDisposable), ByVal theName As String) As RaiiTest Return New RaiiTest(dispList, theName) End Function Public Shared Function newRaiiTest(ByVal theName As String) As RaiiTest Return makeRaii(Of RaiiTest)(AddressOf _newRaiiTest, theName) End Function Shared Sub test(ByVal st As String) Try Using it As RaiiTest = newRaiiTest(st) Debug.Print("Now using object") End Using Debug.Print("No exceptions thrown") Catch ex As raiiException Debug.Print("Output exception: " & ex.Message) If ex.InnerException IsNot Nothing Then Debug.Print("Inner exception: " & ex.InnerException.Message) For Each exx As Exception In ex.DisposalExceptions Debug.Print("Disposal exception: " & exx.Message) Next Catch ex As Exception Debug.Print("Misc. exception: " & ex.Message) End Try End Sub End Class 由于raitest继承了raibase(字符串的),要创建类实例,请使用字符串参数调用newraitest。RAII()是一个泛型函数,将其参数注册为需要清理的iDisposable,然后返回它。当对主对象调用Dispose或在主对象的构造中引发异常时,所有已注册的可处置项都将被处置。 以下是riaaBase类: Option Strict On Class raiiException Inherits Exception ReadOnly _DisposalExceptions() As Exception Sub New(ByVal message As String, ByVal InnerException As Exception, ByVal allInnerExceptions As Exception()) MyBase.New(message, InnerException) _DisposalExceptions = allInnerExceptions End Sub Public Overridable ReadOnly Property DisposalExceptions() As Exception() Get Return _DisposalExceptions End Get End Property End Class Public Class raiiBase(Of T) Implements IDisposable Protected raiiList As Stack(Of IDisposable) Protected creationParam As T Delegate Function raiiFactory(Of TT As raiiBase(Of T))(ByVal theList As Stack(Of IDisposable), ByVal theParam As T) As TT Shared Function CopyFirstParamToSecondAndReturnFalse(Of TT)(ByVal P1 As TT, ByRef P2 As TT) As Boolean P2 = P1 Return False End Function Shared Function makeRaii(Of TT As raiiBase(Of T))(ByVal theFactory As raiiFactory(Of TT), ByVal theParam As T) As TT Dim dispList As New Stack(Of IDisposable) Dim constructionFailureException As Exception = Nothing Try Return theFactory(dispList, theParam) Catch ex As Exception When CopyFirstParamToSecondAndReturnFalse(ex, constructionFailureException) ' The above statement let us find out what exception occurred without having to catch and rethrow Throw ' Should never happen, since we should have returned false above Finally If constructionFailureException IsNot Nothing Then zapList(dispList, constructionFailureException) End If End Try End Function Protected Sub New(ByVal DispList As Stack(Of IDisposable), ByVal Params As T) Me.raiiList = DispList Me.creationParam = Params End Sub Public Shared Sub zapList(ByVal dispList As IEnumerable(Of IDisposable), ByVal triggerEx As Exception) Using theEnum As IEnumerator(Of IDisposable) = dispList.GetEnumerator Try While theEnum.MoveNext theEnum.Current.Dispose() End While Catch ex As Exception Dim exList As New List(Of Exception) exList.Add(ex) While theEnum.MoveNext Try theEnum.Current.Dispose() Catch ex2 As Exception exList.Add(ex2) End Try End While Throw New raiiException("RAII failure", triggerEx, exList.ToArray) End Try End Using End Sub Function RAII(Of U As IDisposable)(ByVal Thing As U) As U raiiList.Push(Thing) Return Thing End Function Shared Sub zap(ByVal Thing As IDisposable) If Thing IsNot Nothing Then Thing.Dispose() End Sub Private raiiBaseDisposeFlag As Integer = 0 ' To detect redundant calls ' IDisposable Protected Overridable Sub Dispose(ByVal disposing As Boolean) If disposing AndAlso Threading.Interlocked.Exchange(raiiBaseDisposeFlag, 1) = 0 Then zapList(raiiList, Nothing) End If 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 请注意,如果对任何或所有已注册的一次性对象的处置失败,将引发自定义异常类型。InnerException将指示构造函数是否失败;要查看哪些处理器失败,请检查DisposalExceptions。 |
4
0
|
5
-2
在C#中,您将使用“using”:
使用这些方法时,即使发生异常,也保证调用Dispose方法。您可以在Dispose方法中释放由初始值设定项(或构造函数)创建的任何资源。 |