For some odd reason, an idea popped into my head based on my post about the Exit Try issue. It's bad idea -- a hack. Yet I couldn't help but let it run it's course.
I started by thinking about the try/finally block that automatically calls "Dispose" on the enumerator. So why not create a custom enumerator that implements IDisposable and in the Dispose method, call Dispose on the object that the enumerator is working on? It would be just like the C# "using" statement...
The Disposable Class
I started by creating a class that implemented IEnumerator and IDisposable. It doesn't actually enumerate anything -- it simply returns, only once, an instance of a class that was passed to its constructor. In the Dispose() method, it calls the Dispose on that same class.
Public Class Disposable Implements IEnumerator Implements IDisposable
Private _obj As Object Private _stage As Stage = Stage.Uninitialized
Public Sub New(ByVal item As Object) _obj = item _stage = Stage.Initialized End Sub
Public Sub Reset() Implements IEnumerator.Reset If Not _obj Is Nothing Then _stage = Stage.Initialized End If End Sub
Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext If _stage <> Stage.Used Then Return True Else Return False End If End Function
Public ReadOnly Property Current() As Object Implements IEnumerator.Current Get _stage = Stage.Used Return _obj End Get End Property
Public Sub Dispose() Implements IDisposable.Dispose DirectCast(_obj, IDisposable).Dispose() End Sub End Class
Public Enum Stage Uninitialized Initialized Used End Enum
Next, I needed to create an IEnumerable object that would take an object, and return my custom enumerator
Public Class Disposer Implements IEnumerable
Private _obj As Object
Public Sub New(ByVal item As Object) _obj = item End Sub
Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator Return New Disposable(_obj) End Function End Class
That's pretty much it!
So I create a small class to test this with:
Public Class Worker Implements IDisposable
Public Sub DoStuff() Console.WriteLine("doing stuff...") End Sub
Public Sub Dispose() Implements IDisposable.Dispose Console.WriteLine("I'm being disposed!") End Sub End Class
And here's the implementation:
Dim wrapper As Disposer = New Disposer(New Worker()) Dim w As Worker
For Each w In wrapper w.DoStuff() Next
Yeah, it's a hack. But hey -- automatic calling of "Dispose" on objects in VB.NET! I guess that's one more feature to remove from the list of "advantages" that C# has over VB.NET... :)