0

I have seen a question here where they implemented a generic dispose method that takes any IDisposable object and calls dispose on it. I would like to make this such that it can take variable number of args. However, I do want to restrict the args to be IDisposable at compile time. (This is because some people in my organization will end up calling this method even on non IDisposable objects "Just to be safe" and "it causes no harm")

I have implemented the same in VB like this. How can I make it take multiple args. Note that I do want them to be passed by reference because I am setting the variable to nothing.

Public Sub DisposeObject(Of TDisposable As IDisposable)(ByRef disposableObject As TDisposable)
    If disposableObject IsNot Nothing Then
        disposableObject.Dispose()
        disposableObject = Nothing
    End If
End Sub
Community
  • 1
  • 1
DevByDefault
  • 664
  • 10
  • 24
  • Looks like someone added the VB.Net tag on this. I did not add that tag because the problem is not specific to VB.Net. Doesnt the same issue exist in C# ?. I changed the tag to .Net. – DevByDefault Aug 31 '10 at 12:03
  • This is based on a fundamental misunderstanding how interfaces, generics, argument passing, IDisposable and the garbage collector works. Too much to chew over in one post, just don't do this. – Hans Passant Aug 31 '10 at 13:24
  • I am still trying to understand why Param does not work with ByRef args. If this is too involved, please let me know andI will close this question. – DevByDefault Sep 02 '10 at 21:20

4 Answers4

1

In VB you get a method with variable number of arguments with the ParamArray modifier on an array parameter.

Note however that ParamArray parameters must be declared ByVal, and changes to the array have no effect in the calling code. So you can't have both variable number of arguments and ByRef semantics.

Mattias S
  • 4,748
  • 2
  • 17
  • 18
0
Public Sub DisposeObjects(Of T As IDisposable)(ByRef disposableObject As T)
    Dim disposable As IDisposable = CType(disposableObject, T)
    disposableObject = CType(Nothing, T)
    If (disposable IsNot Nothing) Then
        disposable.Dispose()
    End If
End Sub

Usage:

Dim any as Foo = New Foo

DisposeObjects(CType(any, Foo))

silver
  • 13
  • 3
0

Donno VB but in C# you could write:

public void DisposeObjects(params IDisposable[] args)
{
  foreach(IDisposable obj in args)
  {
     if(obj != null)
     {
        obj.Dispose();
     }
  }
}
Adrian Zanescu
  • 7,907
  • 6
  • 35
  • 53
  • This way, I would have to pass in IDisposable variable meaning I have to assign an IDisposable variable to any object that I want to be disposed and pass that in. It leave me to set the original variable to nothing in the calling code which is no good. – DevByDefault Jan 27 '11 at 17:09
0

Here is how you do it:

Public Sub DisposeObject(ByVal ParamArray disposableObjects() As IDisposable)
    For Each obj As IDisposable In disposableObjects
        If Not IsNothing(obj) Then obj.Dispose()
    Next
End Sub

But I do not recommend such a solution. It's much better to use the "using" statement.

In c#

using (var obj = new TypeImlementingIdisposable)
{
   //do stuff with the object here
}

and in vb:

Using obj As New TypeImlementingIdisposable
   ' do stuff with the object here
End Using

This ensures that the objects always are disposed, not matter if an exception is thrown or not.

You can read more at msdn

jgauffin
  • 99,844
  • 45
  • 235
  • 372
  • I agree that using "Using" is a better way, but at the moment the only change I can make to existing code is in the Finally block. I will be calling this method in the Finally Blocks, that way they will get disposed even on Exceptions. – DevByDefault Aug 31 '10 at 15:57