Calling Dispose instead of close, clear, ....

J

Joop

Hello,

I've written the following little helper function which calls Dispose on
classes which implement the idisposable interface.

Public Sub DisposeObject(ByVal DisposeAbleObject As IDisposable)
If Not DisposeAbleObject Is Nothing Then
DisposeAbleObject.Dispose()
End If
End Sub

The reason for this is to avoid ugly looking finally clauses with lots
of checking if an object ref is nothing before calling dispose on them.
For example in a try finally block in which a connection is opnened, a
transaction is started and an sqldatareader gets created which looks
like this:

try
......
finally
if sqlconnection is nothing then
sqlconnection.close
end if

if Transaction is nothing then
Transaction.dispose
end if

if Datareader is nothing then
Datareader.close
end if
end try

i'd write this:

try
.....
finally
disposeobject(sqlconnection)
disposeobject(transaction)
disposeobject(sqldatareader)
end try

a lot better looking IMO. I dont have to worry about whether the ref is
nothing or not.

Now my question is this: Is this going to cause any strange behavior?
I've tested it and it seems to work.. but im wondering if there could be
any side effects since im not calling the specific Close of the
datareader or sqlconnection, im calling the Dispose. The documentation
says there's not much difference in calling Dispose instead of Close on
a connection, but can i assume the same for any object that implements
IDisposable?

Thanks
 
I

Imran Koradia

Just one point - are you sure that whenever you call DisposeObject on an
object, the object is actually implementing the IDisposable interface? I
would rather do something like this for added protection:

Sub DisposeObject(ByVal DisposableObject As Object)
If Not DisposableObject Is Nothing Then
If TypeOf DisposableObject Is IDisposable Then
DirectCast(DisposableObject, IDisposable).Dispose()
Else
' do nothing..or throw some error..whatever..
End If
End If
End Sub

Imran.
 
D

Daniel O'Connell [C# MVP]

Imran Koradia said:
Just one point - are you sure that whenever you call DisposeObject on an
object, the object is actually implementing the IDisposable interface? I
would rather do something like this for added protection:

Shouldn't it refuse to compile if its not the correct type?
 
I

Imran Koradia

Well - it would throw up the curly underlines if you have option strict on.
With option strict off, its not going to complain at all until you hit the
function during runtime. Ofcourse, we all know that its best to turn option
strict on but there might be circumstances that would force one to turn it
off (for example, late binding) or a developer simply didn't turn it on :)
Considering its a common subroutine, it shouldn't be too much to add an
extra check. Just my 2 cents.

Imran.
 
M

Michael

No you cannot ASSUME close and disclose are the same , otherwise, why two
method? if you use Reflector to check the code for Close(), you will see it
calls Dispose().
Check MSDN for Dispose() on Connection object give you why.

Mike
 
D

Daniel O'Connell [C# MVP]

Imran Koradia said:
Well - it would throw up the curly underlines if you have option strict
on. With option strict off, its not going to complain at all until you hit
the function during runtime. Ofcourse, we all know that its best to turn
option strict on but there might be circumstances that would force one to
turn it off (for example, late binding) or a developer simply didn't turn
it on :) Considering its a common subroutine, it shouldn't be too much to
add an extra check. Just my 2 cents.

*shrug*, I don't generally think like that.

However, in the coming versions of VB, won't they be adding a Using
statement?
 
J

Jay B. Harlow [MVP - Outlook]

Imran,
Why change the DisposableObject parameter to Object?

Joop's original function will have a compile error with Option Strict On,
and a runtime error with Option Strict Off & a loosely typed variable.

For example:

Option Strict On
Dim o As Object
DisposeObject(o) ' causes a compile error

Option Strict Off
Dim o As Object
DisposeObject(o) ' causes an InvalidCastException at runtime

In fact Joop's version will cause compile time errors with Option Strict Off
if its obvious that the parameter does not support IDisposable (for example
you pass a non inheritable class or structure).

Option Strict Off
Dim o As String
DisposeObject(o) ' causes a compile error

I don't see what changing the parameter to Object & explicitly checking for
IDisposable is buying you, as the compiler will do that for you with Joop's
original function.

In fact your version causes runtime errors with both Option Strict On & Off,
which IMHO is rarely desirable!

Of course I may be missing something...

Hope this helps
Jay
 
I

Imran Koradia

Jay B. Harlow said:
Imran,
Why change the DisposableObject parameter to Object?

Joop's original function will have a compile error with Option Strict On,
and a runtime error with Option Strict Off & a loosely typed variable.

For example:

Option Strict On
Dim o As Object
DisposeObject(o) ' causes a compile error

Correct. I mentioned in my second post that we're only looking at option
strict off which I should have mentioned in my first post :-S. Joop's
technique is perfectly alright when option strict is on.
Option Strict Off
Dim o As Object
DisposeObject(o) ' causes an InvalidCastException at runtime

Thats the point - its throwing an exception when its not really needed and
one that can be avoided, IMHO.
In fact Joop's version will cause compile time errors with Option Strict
Off if its obvious that the parameter does not support IDisposable (for
example you pass a non inheritable class or structure).

Option Strict Off
Dim o As String
DisposeObject(o) ' causes a compile error

I don't see what changing the parameter to Object & explicitly checking
for IDisposable is buying you, as the compiler will do that for you with
Joop's original function.

In fact your version causes runtime errors with both Option Strict On &
Off, which IMHO is rarely desirable!

Why would the version I sent cause a runtime exception ?!? In fact it will
never ever throw a runtime exception since its going to dispose off only
those objects that implement the IDisposable interface. So unless an
exception is thrown from within the dispose, I don't see how that version
would result in a runtime exception.


Imran.
 
I

Imran Koradia

If I'm not mistaken, you're implying setting option strict on in each file
for which I suppose C# uses the 'using' syntax (I'm not too familiar with
C# - apologies for any mistakes). In VB, you just say 'Option Strict On'.
However, the rule is to set it at the project level so I'm not sure if its
too common to do that for each file. However, I'm far less experienced to be
a good judge of common usage.

Imran.
 
J

Joop

Daniel said:
*shrug*, I don't generally think like that.

However, in the coming versions of VB, won't they be adding a Using
statement?

Daniel: Yes, the using statement is exactly what im trying to emulate.

Imran: by using "ByVal DisposeAbleObject As IDisposable" there always is
a dispose method on the object i want to dispose, i dont need to check
that at runtime, the compiler does that for me at design time.
 
J

Joop

I know the diff. between dispose and close on a connection, and for me
dispose would work for me. Most streams and other disposable objects
*seem* to be happy when you call dispose no them.

I just wonder, how does C# know which method to call in a Using
statement..? since im trying to emulate this behaviour in VB
 
J

Jon Skeet [C# MVP]

Imran Koradia said:
If I'm not mistaken, you're implying setting option strict on in each file
for which I suppose C# uses the 'using' syntax (I'm not too familiar with
C# - apologies for any mistakes).

No, Daniel was talking about the C# using statement which allows you to
write:

using (Stream s = new FileStream("hello"))
{
...
}

This is converted into a try/finally block which automatically calls
Dispose. Apparently this will be available in the next version of
VB.NET.
 
J

Joop

Jon said:
No, Daniel was talking about the C# using statement which allows you to
write:

using (Stream s = new FileStream("hello"))
{
...
}

This is converted into a try/finally block which automatically calls
Dispose. Apparently this will be available in the next version of
VB.NET.

Returning to my original post -

The using statement in C# is doing exactly the same thing as my code
does? Calling Dispose regardless of the availability of a more specific
disposing method (eg .Close) on a class?
 
J

Jon Skeet [C# MVP]

Joop said:
Returning to my original post -

The using statement in C# is doing exactly the same thing as my code
does? Calling Dispose regardless of the availability of a more specific
disposing method (eg .Close) on a class?

Yes, it does. It couldn't do anything else, really, without some extra
information somewhere in the metadata to say what to call.

I would consider any implementation of IDisposable which didn't do
enough to let someone use the "using" statement without worrying about
other resources to be broken.
 
I

Imran Koradia

gotcha..thanks!

Jon Skeet said:
No, Daniel was talking about the C# using statement which allows you to
write:

using (Stream s = new FileStream("hello"))
{
...
}

This is converted into a try/finally block which automatically calls
Dispose. Apparently this will be available in the next version of
VB.NET.
 
J

Jay B. Harlow [MVP - Outlook]

Imran,
Why would the version I sent cause a runtime exception ?!? In fact it will
Sub DisposeObject(ByVal DisposableObject As Object)
If Not DisposableObject Is Nothing Then
If TypeOf DisposableObject Is IDisposable Then
DirectCast(DisposableObject, IDisposable).Dispose()
Else
' do nothing..or throw some error..whatever..
End If
End If
End Sub

Your "or throw some error" comment in your source (if implemented). Which
will occur for actual objects that do not implement IDisposable.
Unfortunately my sample throws an exception for Nothing also.

My point is more that you are relying entirely on runtime error checking,
IMHO compile time error checking is preferred even with Option Strict Off!

Which is why, looking back (thinking back) when I played with a
DisposeObject routine I overloaded the routine. The As Object version
performs mostly like yours while the As IDisposable performs like Joops.

Something like:

Sub DisposeObject(ByVal DisposableObject As Object)
If Not DisposableObject Is Nothing Then
DirectCast(DisposableObject, IDisposable).Dispose()
End If
End Sub

Public Sub DisposeObject(ByVal DisposeAbleObject As IDisposable)
If Not DisposeAbleObject Is Nothing Then
DisposeAbleObject.Dispose()
End If
End Sub

For strongly typed variables the As IDisposable version will be called, no
casting needed, for loosely typed variables the As Object version will be
called, the DirectCast will raise an exception if the object is not
IDisposable, I would use TypeOf as you did if I actually wanted to avoid the
exception (I don't have my project handy where I was using a DisposeObject
routine).

Hope this helps
Jay
 
I

Imran Koradia

Yup - the overloaded version does make it more complete. And yes I
absolutely agree that compile time check is the preferred way. Sounds good
to me :) Btw, is the 'Using' keyword already in VB2005 Beta1?

Thanks!
Imran.
 
J

Joop

Jon said:
Yes, it does. It couldn't do anything else, really, without some extra
information somewhere in the metadata to say what to call.

I would consider any implementation of IDisposable which didn't do
enough to let someone use the "using" statement without worrying about
other resources to be broken.

This is sortof what i was thinking. The only thing i was a bit worried
about was that the using statement would look for some attribute or
perform some other sort of magic.

Thanks everyone who replied
 
J

Jay B. Harlow [MVP - Outlook]

Imran,
Btw, is the 'Using' keyword already in VB2005 Beta1?

Yes. You can do something like:

Using stream As New System.IO.FileStream("myfile.txt",
IO.FileMode.Open)
Using reader As New System.IO.StreamReader(stream)
Dim line As String
line = reader.ReadLine()
Do Until line Is Nothing
' do something with line
line = reader.ReadLine()
Loop
End Using
End Using

There's a way to collapse the above to a single statement, however I do not
have that handy...

For details see:
http://msdn2.microsoft.com/library/htd05whh.aspx

and:

http://msdn2.microsoft.com/library/wydd5hkd.aspx


Hope this helps
Jay
 
I

Imran Koradia

Interesting. I guess this should be a useful addition in VB2005.

Thanks for the info, Jay.
Imran.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top