Use IDisposable for general clean-up code?

S

Samuel R. Neff

I'd like some opinions on whether or not to use IDisposable for
classes that require clean-up but when the clean-up is not related to
unmanaged resources or other disposable objects.

The most descriptive case is unit test data. We have unit test data
classes that generate fake data in the database which we can then test
against, and then the unit test data classes delete those records.

We can have all of these test data classes implement IDisposable and
the Dispose method can clean up the data (not during garbage
collection of course..only when someone actually calls Dispose).

An alternative viewpoint that's been suggested is that this is an
abuse of IDisposable and we instead should just have a CleanUp method
or something similar that cleans stuff up and all developers have to
know to call CleanUp.

What are pro's and con's of each approach? Are there any established
standards of what not to use IDisposable for?

Thanks,

Sam
 
N

Nicholas Paldino [.NET/C# MVP]

Samuel,

I agree with your use of IDisposable. I don't agree with the
documentation regarding IDisposable, that it is only for managed resources.
The way I see it, it is used for whenever you need deterministic
finalization semantics.

Additionally, you have language support for doing this. To not use
IDisposable would be a huge burden on the coder.

However, I will say this, unless you have some other reason not to do
this, you might want to run your test cases in a transaction and abort the
transaction when the test is complete. This way, you don't have to delete
your fake data, it's done automatically.

Hope this helps.
 
S

Samuel R. Neff

We don't abort the transaction because left-over test data is a sign
of a bad test (or insufficient tests). If we don't properly clean up
the data, then there is a problem with the test or class being tested
that has to be corrected. All test data we generate is tagged as test
data so we can find it later. We've found bugs in both our tests and
in our real code that only manifested themselves as left-over test
data.

Thanks,

Sam
 
X

xAvailx

The most descriptive case is unit test data. We have unit test data
classes that generate fake data in the database which we can then test
against, and then the unit test data classes delete those records. <<

Not related to your IDisposable question but unit testing. What we do
is in the tests' setup, we have a helper class that brings the database
to a known state. This either involves:
1-)Dropping and recreating all database objects and setting up the
known test data, however, it is very time consuming as this needs to be
done for every test
2-)Or, Setup the know test data which requires any previous data to be
deleted.

Number 2 is much quicker because it doesn't require dropping all the
tables, stored procs, views etc...Basically all it does is runs a
script that deletes all data in the database, and then runs a separate
script that adds all the known test data in the entire database. This
is all encapsulated in a helper class, thus all we need to do is
something like: HelperClass.ReinstateDb(); and the database is ready.

HTH.
 
K

Kevin Yu [MSFT]

Hi Sam,

I agree with the concept you have on IDisposable. But cleaning up the test
data is not done by IDisposable. Since you have tags on your test data, you
can clean them later with other codes that searches the database for test
data.

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."
 
H

Helge Jensen

Samuel said:
An alternative viewpoint that's been suggested is that this is an
abuse of IDisposable and we instead should just have a CleanUp method
or something similar that cleans stuff up and all developers have to
know to call CleanUp.

You can "check" for forgotten Dispose() by declaring a destructor:

public class Foo: IDisposable {
public void Dispose() {
GC.SuppressFinalize(this);
// more code
}
~Foo() {
ForgottenDisposes.Global.Happened(this);
Dispose();
}
}

You can have ForgottenDisposes.Global.Happened throw an exception, that
will break the debugger at the offending spot.

You can selectively change what Happend does, throw, log and ignore
comes to mind as valid options, depending on whether a debugger is
attached and possibly some configuration.

If the call to Happened returns, your application will *try* to
Dispose() the data-structure at garbage-collection-time, even though the
programmer forgot.
What are pro's and con's of each approach? Are there any established
standards of what not to use IDisposable for?

IDisposable is a good choice for places where the code, not the GC,
should decide when to clean up.
 

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