What are IDisposable alternative uses? - c#

The msdn documentation of the System.IDisposable interface states that
The primary use of this interface is to release unmanaged resources.
I'm wondering what are alternative uses.
For example we also needed the IDisposable interface for other allocated resources, such as event subscription and so.
We used the interface as a marker to allow a class instance to know when it's no more used from clients. Client and infrastructural code explicitly call IDisposable.Dispose() whenever they no more need a logical instance of a class implementing the code.
There's no relation with unmanaged resources wrapped from the interface.
When we choosed the IDisposable interface for such a behaviour we considered it as an alternative (undocumented) use of the interface.
Which are the alternative use of IDisposable you have found?
Are they legittimate? Is the MSDN documentation wrong?

I think your reading of the documentation is wrong. Saying that any usage of IDisposable that is not related to unmanaged resources is undocumented is a bit like saying that any usage of System.Int32 that is not counting things is undocumented. It is an interface and has no implementation, there is no functionality there to even begin distinguishing between what's documented and what's undocumented.
The purpose of IDisposable is simply to provide the developer with a mechanism to deterministically control the lifetime of their objects. It just so happens that this mainly a requirement for dealing with unmanaged resources.
One of the more fancy uses of IDisposable is the using block syntactic sugar. As others have mentioned, using blocks give an operation scope and I think those are quite elegant.
Example 1 - timing blocks
StackOverflow uses mini profiler that uses using blocks to identify nested regions of execution:
using (profiler.Step("Doing complex stuff"))
{
using (profiler.Step("Step A"))
{ // something more interesting here
Thread.Sleep(100);
}
using (profiler.Step("Step B"))
{ // and here
Thread.Sleep(250);
}
}
The alternative to not using using is pretty horrible and I don't even want to mock it up here.
Example 2 - Disposable action
There have been different variations of disposable action pattern making rounds in .NET Domain Driven Design circles. Ayende has one, so does Udi Dahan in his Domain Events implementation, Jimmmy Bogard has a slightly different take on this, still in the context of Domain Events. The crux of the pattern is that you want to perform certain actions in some context, then have the context revert back to what it was before after you are done.
Ayende provides a simple example:
class UsuallyReadOnly {
//.. implementation
public IDisposable AllowModification
{
get
{
_allowModification = true;
return new DisposableAction(()=>{ _allowModification = false; } );
}
}
}
And UsuallyReadOnly's usage:
UsuallyReadOnly foo = new UsuallyReadOnly();
using(foo.AllowModification)
{
foo.Name = "Bar";
}

IDisposable is often used in conjunction with using to activate and deactivate something in a definite scope even if it is not an unmanaged resource. The use you describes sound as a reference counting and for sure is not recommended.

For "resources", substitute "responsibilities". When an object is said to hold an unmanaged resource, what that really means is that there is some task that needs to get done sometime, and the object is the only thing with the information and impetus necessary to do it. The purpose of "Dispose" isn't to get rid of any tangible entity, but rather to allow an object to "put its affairs in order". Someone is putting his affairs in order before his death isn't doing anything to himself, but rather he is ensuring that the things he has to do to persons and things outside himself get done. Likewise with IDisposable.Dispose.

Remember there is also the using pattern which acts a bit like RAII.
using ( DisposableObject obj = new DisposableObject( ) )
{
.....
}
So Dispose gets called when the using block is exited.

One of the more popular uses of the IDisposable interface is transaction scopes. You can use it to wrap some SQL logic in a transaction, and explicitly call Complete() to end the transaction:
using (var scope = new TransactionScope())
{
using (var connection = new SqlConnection(connectString))
{
// perform sql logic
...
scope.Complete();
}
}
You could also use a similar pattern for just about anything that requires a temporary function, such as creating and deleting a temporary file:
public class TempFileProvider : IDisposable
{
public Filename { get; private set; }
public TempFileProvider()
{
Filename = Path.GetTempFileName();
}
public void Dispose()
{
File.Delete(Filename);
}
}
So you could use it like:
using (var tempFileProvider = new TempFileProvider())
{
DoSomethingWithFile(tempFileProvider.Filename);
} // deletes temp file

Have a look at the following question Need an alternative to my IDisposable Hack
There i give a nice example of what i used IDisposable for. :)
Granted, it is not the ideal solution, however, it helped me a lot.

Related

"using" construct and exception handling

The "using" construct looks incredibly handy for situations that require both beginning and separated end parts.
Quick example to illustrate:
using (new Tag("body")) {
Trace.WriteLine("hello!");
}
// ...
class Tag : IDisposable {
String name;
public Tag(String name) {
this.name = name;
Trace.WriteLine("<" + this.name + ">");
Trace.Indent();
}
public void Dispose() {
Trace.Unindent();
Trace.WriteLine("</" + this.name + ">")
}
}
The beginning part is defined as the constructor, the end part is the Dispose method.
However despite of being attractive this construct has a serious caveat that comes from the fact that the Dispose method is called from within a finally block. So there are 2 problems:
You should avoid throwing exceptions from the finally block because they will override the original exception that was supposed to be caught.
There is no way of knowing inside of the Dispose method if an exception was thrown earlier between "beginning" and "end" and thus there is no way of handling the "end" part accordingly.
These 2 things make using of this construct impractical which is a very sad fact.
Now, my questions are:
Is my understanding of the problems right? Is this how "using" actually works?
If so, is there any way to overcome these problems and make practical use of the "using" construct other than what it was originally designed for (releasing resources and cleaning up)
In case there is no practical way for "using" to be used this way. What are the alternative approaches (to enforce the context over some code with the beginning and end parts)?
Your rule #1 applies with or without using, so the rule #2 is the real decider: opt for a try/catch if you must distinguish between situations when an exception has been thrown and the normal program completion.
For example, if your persistence layer may discover issues in the process of using a database connection, your connection needs to close regardless of the fact that there was an exception. In this case, the using construct is a perfect choice.
In some cases you can set up using specifically to detect normal completion vs. an exceptional completion. Ambient transactions provide a perfect example:
using(TransactionScope scope = new TransactionScope()) {
// Do something that may throw an exception
scope.Complete();
}
If scope's Dispose is called before Complete has been called, TransactionScope knows that an exception has been thrown, and aborts the transaction.
The intent of the using statement and of the IDisposable interface is for the user to dispose of unmanaged resources. These resources are usually expensive and precious, so they must be disposed of no matter what (that's why it's on the finally). Code in finally blocks can't even be aborted, and it can hang a whole app domain shutdown.
Now, it's very tempting to abuse using for the purposes you're describing, and I've done that in the past. Most of the time there's no danger there. But if an unexpected exception happens, the whole state of the processing is compromised, you wouldn't necessarily want to run the end operation; so in general, don't do this.
An alternative is to use a lambda, something like this:
public interface IScopable {
void EndScope();
}
public class Tag : IScopable {
private string name;
public Tag(string name) {
this.name = name;
Trace.WriteLine("<" + this.name + ">");
Trace.Indent();
}
public void EndScope() {
Trace.Unindent();
Trace.WriteLine("</" + this.name + ">");
}
}
public static class Scoping {
public static void Scope<T>(this T scopable, Action<T> action)
where T : IScopable {
action(scopable);
scopable.EndScope();
}
}
Use it like this:
new Tag("body").Scope(_ =>
Trace.WriteLine("hello!")
);
You can also create other implementations that run certain actions based on whether exceptions were raised of not.
In Nemerle, the language can be extended with new syntax to support this.
I dont know if this was the original intention of IDisposable, but Microsoft certanly ARE using it the way you describe (separating begin and end parts). A good example for it is the MVCForm class, provided by the mvc infrastracture. It implements IDisposable and writes the end tag for the form, while i cant see its implementation releasing ant resources (the writer used there to ouput the html seems to stay alive even after the form is disposed).
Alot has been written about the using block and how it "swallows" exceptions (a wcf client is a good sample, you can also find such discussions here, on SO). Personally i also feel alot of times that as much as it is convinient to use the using block, its not really 100% clear when it should and when it should not be used.
Of course, you actually CAN tell within the dispose method if you reached it with our without an error, by adding an extra flag to your class, and raising it within the using block, but this will work only if the person who will use your class will be aware of that flag
You are correct in observing a problem with the design of try/finally blocks, which is in turn a problem with using: there is no clean way for code in a finally block to know whether code execution will continue with the statement following the finally block, or whether there is a pending exception which will be effectively take over as soon as the finally block executes.
I would really like to see a language feature in vb.net and C# which would allow a finally block to include an Exception parameter (e.g.
try
{
}
finally (Exception ex)
{
...
}
where the passed-in exception would be null if the try block exited normally, or would hold an exception if it did not. Along with this, I would like to see an IDisposableEx interface, which would inherit Dispose, and include a Dispose(Exception ex) method with the expectation that user code would pass in the ex from the finally block. Any exceptions which occurred during the Dispose could then wrap the passed-in exception (since both the passed-in exception, and the fact that an exception occurred in Dispose, would be relevant).
Failing that, it might be helpful to have .net provide a method which would indicate whether there was an exception pending in the current context. Unfortunately, it's not clear what the exact semantics of such a method should be in various corner cases. By contrast, the semantics of finally (Exception ex) would be perfectly clear. Note, incidentally, that a proper implementation of finally (Exception ex) would require that the language make use of exception filters, but would not require exposing the ability to create arbitrary filters.
In my opinion you are misusing the IDisposable interface.
A common practice is to use the interface to release unmanaged resources. Normally, the garbage collector will clean up objects, but in some cases - When yo do NOT longer need the object - you might need to manually clean up.
However in your case, you are not cleaning up an object that is not needed anymore; you are using it to force some logic. You should use another design for that.

Disposing client after creation with WebChannelFactory

In my current production code, and according to documentation on msdn, the way to create a client is this
using (WebChannelFactory<IServiceInterface> cf
= new WebChannelFactory<IServiceInterface>("http://service.url"))
{
IServiceInterface client = cf.CreateChannel();
client.CallTheMethod();
}
given that I have this interface:
public interface IServiceInterface
{
void CallTheMethod();
}
However I noticed that the object client created by the WebChannelFactory also implements IDisposable. So I want to dispose this object also. I didn't find any other way than:
using (WebChannelFactory<IServiceInterface> cf
= new WebChannelFactory<IServiceInterface>("http://service.url"))
using(IDisposable client = (IDisposable)cf.CreateChannel())
{
((IServiceInterface)client).CallTheMethod();
}
I find this ugly. So :
Do I really need to dispose it ? I mean that may be it is disposed when you disposed the factory (if the factory keeps a reference to every object it has created maybe) ?
If yes, do you have a better way ?
This is a very complex issue. Even by Microsoft's own admission, disposing of channel factories was a bad design which was changed multiple times so short answer is no, you need to use something alternative to it.
Here is an alternative method to disposing.

A question of style/readability regarding the C# "using" statement

I'd like to know your opinion on a matter of coding style that I'm on the fence about. I realize there probably isn't a definitive answer, but I'd like to see if there is a strong preference in one direction or the other.
I'm going through a solution adding using statements in quite a few places. Often I will come across something like so:
{
log = new log();
log.SomeProperty = something; // several of these
log.Connection = new OracleConnection("...");
log.InsertData(); // this is where log.Connection will be used
... // do other stuff with log, but connection won't be used again
}
where log.Connection is an OracleConnection, which implements IDisposable.
The neatnik in me wants to change it to:
{
using (OracleConnection connection = new OracleConnection("..."))
{
log = new log();
log.SomeProperty = something;
log.Connection = conn;
log.InsertData();
...
}
}
But the lover of brevity and getting-the-job-done-slightly-faster wants to do:
{
log = new log();
log.SomeProperty = something;
using (log.Connection = new OracleConnection("..."))
log.InsertData();
...
}
For some reason I feel a bit dirty doing this. Do you consider this bad or not? If you think this is bad, why? If it's good, why?
EDIT: Please note that this is just one (somewhat contrived) example of many. Please don't fixate on the fact that this happens to indicate a logger class with a poorly thought-out interface. This is not relevant to my question, and I'm not at liberty to improve the classes themselves anyway.
They are both horrid. Do neither of them.
You're making what I call a "high maintenance class" here. The high maintenance class has a contract that says "I require you to give me a bunch of resources, and you're required to know when I'm done with them and clean them up appropriately". This contract means that the user of the class has to know how the class is implemented, thereby violating the principle of encapsulation and abstraction that motivated making a class in the first place.
You can tell this by your comment: this is where the connection is used, I know the connection will not be used again. How do you know that? You only know that if that is the documented contract of the class. That's not a good contract to impose upon the consumer of a class.
Some ways to make this better:
1) make the logger disposable. Have it clean up the connection when it is done. The down side of this is that the logger holds on to the connection for longer than necessary.
2) make InsertData take the connection as a parameter. The caller can still be responsible for cleaning up the connection because the logger does not hold onto it.
3) make a third class "Inserter" which is disposable and takes a log and a connection in its constructor. The inserter disposes of the connection when it is disposed; the caller then is responsible for disposing the inserter.
I agree that ideally log itself should implement IDisposable, but let's assume that's not possible and address the question the OP actually asked.
The second way is better, simply because it's less code that accomplishes the same thing. There is no advantage to introducing an additional connection variable here.
Also note that you could do other initialisation outside of the using block. It won't matter here, but may matter if you're "using" some really expensive resource. That is:
log = new log();
log.SomeProperty = something; // This can be outside the "using"
using (OracleConnection connection = new OracleConnection("..."))
{
log.Connection = conn;
log.InsertData();
...
}
I would listen to the neatnik in you. I like his way better personally.
The two ways of using using are totally equivalent. Either way, you end up with a log that's still in scope but has a disposed connection. It's way better to make the log disposable and have its dispose method dispose of its connection, putting the log in the using statement, not the connection itself.
If log implements IDisposable, then do the second choice, as the braces are explicit. In some cases you can use multiple using statements:
using (Graphics g = ...)
using (Pen p = new Pen ...)
using (Font f = new Font ...)
{
}
where you can get away with only using 1 set of braces. This avoids crazy indents.

Using Wrapper objects to Properly clean up excel interop objects

All of these questions:
Excel 2007 Hangs When Closing via .NET
How to properly clean up Excel interop objects in C#
How to properly clean up interop objects in C#
struggle with the problem that C# does not release the Excel COM objects properly after using them. There are mainly two directions of working around this issue:
Kill the Excel process when Excel is not used anymore.
Take care to explicitly assign each COM object used to a variable first and to guarantee that eventually, Marshal.ReleaseComObject is executed on each.
Some have stated that 2 is too tedious and there is always some uncertainty whether you forget to stick to this rule at some places in the code. Still 1 seems dirty and error-prone to me, also I guess that in a restricted environment trying to kill a process could raise a security error.
So I've been thinking about solving 2 by creating another proxy object model which mimics the Excel object model (for me, it would suffice to implement the objects I actually need). The principle would look as follows:
Each Excel Interop class has its proxy which wraps an object of that class.
The proxy releases the COM object in its finalizer.
The proxy mimics the interface of the Interop class.
Any methods that originally returned a COM object are changed to return a proxy instead. The other methods simply delegate the implementation to the inner COM object.
Example:
public class Application
{
private Microsoft.Office.Interop.Excel.Application innerApplication
= new Microsoft.Office.Interop.Excel.Application innerApplication();
~Application()
{
Marshal.ReleaseCOMObject(innerApplication);
innerApplication = null;
}
public Workbooks Workbooks
{
get { return new Workbooks(innerApplication.Workbooks); }
}
}
public class Workbooks
{
private Microsoft.Office.Interop.Excel.Workbooks innerWorkbooks;
Workbooks(Microsoft.Office.Interop.Excel.Workbooks innerWorkbooks)
{
this.innerWorkbooks = innerWorkbooks;
}
~Workbooks()
{
Marshal.ReleaseCOMObject(innerWorkbooks);
innerWorkbooks = null;
}
}
My questions to you are in particular:
Who finds this a bad idea and why?
Who finds this a gread idea? If so, why hasn't anybody implemented/published such a model yet? Is it only due to the effort, or am I missing a killing problem with that idea?
Is it impossible/bad/error-prone to do the ReleaseCOMObject in the finalizer? (I've only seen proposals to put it in a Dispose() rather than in a finalizer - why?)
If the approach makes sense, any suggestions to improve it?
Is it impossible/bad/dangerous to do the ReleaseCOMObject in the destructor? (I've only seen proposals to put it in a Dispose() rather than in a destructor - why?)
It is recommended not to put your clean up code in the finalizer because unlike the destructor in C++ it is not called deterministically. It might be called shortly after the object goes out of scope. It might take an hour. It might never be called. In general if you want to dispose unmanaged objects you should use the IDisposable pattern and not the finalizer.
This solution that you linked to attempts to work around that problem by explicitly calling the garbage collector and waiting for the finalizers to complete. This is really not recommended in general but for this particular situation some people consider it to be an acceptable solution due to the difficulty of keeping track of all the temporary unmanaged objects that get created. But explicitly cleaning up is the proper way of doing it. However given the difficulty of doing so, this "hack" may be acceptable. Note that this solution is probably better than the idea you proposed.
If instead you want to try to explicitly clean up, the "don't use two dots with COM objects" guideline will help you to remember to keep a reference to every object you create so that you can clean them up when you're done.
We use the LifetimeScope class that was described in the MSDN magazine. Using it properly cleans up objects and has worked great with our Excel exports. The code can be downloaded here and also contains the magazine article:
http://lifetimescope.codeplex.com/SourceControl/changeset/changes/1266
Look at my project MS Office for .NET. There is solved problem with referencich wrapper objects and native objects via native VB.NET late-binding ability.
What I'd do:
class ScopedCleanup<T> : IDisposable where T : class
{
readonly Action<T> cleanup;
public ScopedCleanup(T o, Action<T> cleanup)
{
this.Object = o;
this.cleanup = cleanup;
}
public T Object { get; private set; }
#region IDisposable Members
public void Dispose()
{
if (Object != null)
{
if(cleanup != null)
cleanup(Object);
Object = null;
GC.SuppressFinalize(this);
}
}
#endregion
~ScopedCleanup() { Dispose(); }
}
static ScopedCleanup<T> CleanupObject<T>(T o, Action<T> cleanup) where T : class
{
return new ScopedCleanup<T>(o, cleanup);
}
static ScopedCleanup<ComType> CleanupComObject<ComType>(ComType comObject, Action<ComType> actionBeforeRelease) where ComType : class
{
return
CleanupObject(
comObject,
o =>
{
if(actionBeforeRelease != null)
actionBeforeRelease(o);
Marshal.ReleaseComObject(o);
}
);
}
static ScopedCleanup<ComType> CleanupComObject<ComType>(ComType comObject) where ComType : class
{
return CleanupComObject(comObject, null);
}
Usage case. Note the call to Quit, which seems to be necessary to make the process end:
using (var excel = CleanupComObject(new Excel.Application(), o => o.Quit()))
using (var workbooks = CleanupComObject(excel.Object.Workbooks))
{
...
}
For what it's worth, the Excel Refresh Service on codeplex uses this logic:
public static void UsingCOM<T>(T reference, Action<T> doThis) where T : class
{
if (reference == null) return;
try
{
doThis(reference);
}
finally
{
Marshal.ReleaseComObject(reference);
}
}

Method knows too much about methods it's calling

I have a method that I want to be "transactional" in the abstract sense. It calls two methods that happen to do stuff with the database, but this method doesn't know that.
public void DoOperation()
{
using (var tx = new TransactionScope())
{
Method1();
Method2();
tc.Complete();
}
}
public void Method1()
{
using (var connection = new DbConnectionScope())
{
// Write some data here
}
}
public void Method2()
{
using (var connection = new DbConnectionScope())
{
// Update some data here
}
}
Because in real terms the TransactionScope means that a database transaction will be used, we have an issue where it could well be promoted to a Distributed Transaction, if we get two different connections from the pool.
I could fix this by wrapping the DoOperation() method in a ConnectionScope:
public void DoOperation()
{
using (var tx = new TransactionScope())
using (var connection = new DbConnectionScope())
{
Method1();
Method2();
tc.Complete();
}
}
I made DbConnectionScope myself for just such a purpose, so that I don't have to pass connection objects to sub-methods (this is more contrived example than my real issue). I got the idea from this article: http://msdn.microsoft.com/en-us/magazine/cc300805.aspx
However I don't like this workaround as it means DoOperation now has knowledge that the methods it's calling may use a connection (and possibly a different connection each). How could I refactor this to resolve the issue?
One idea I'm thinking of is creating a more general OperationScope, so that when teamed up with a custom Castle Windsor lifestyle I'll write, will mean any component requested of the container with OperationScopeLifetyle will always get the same instance of that component. This does solve the problem because OperationScope is more ambiguous than DbConnectionScope.
I'm seeing conflicting requirements here.
On the one hand, you don't want DoOperation to have any awareness of the fact that a database connection is being used for its sub-operations.
On the other hand, it clearly is aware of this fact because it uses a TransactionScope.
I can sort of understand what you're getting at when you say you want it to be transactional in the abstract sense, but my take on this is that it's virtually impossible (no, scratch that - completely impossible) to describe a transaction in such abstract terms. Let's just say you have a class like this:
class ConvolutedBusinessLogic
{
public void Splork(MyWidget widget)
{
if (widget.Validate())
{
widgetRepository.Save(widget);
widget.LastSaved = DateTime.Now;
OnSaved(new WidgetSavedEventArgs(widget));
}
else
{
Log.Error("Could not save MyWidget due to a validation error.");
SendEmailAlert(new WidgetValidationAlert(widget));
}
}
}
This class is doing at least two things that probably can't be rolled back (setting the property of a class and executing an event handler, which might for example cascade-update some controls on a form), and at least two more things that definitely can't be rolled back (appending to a log file somewhere and sending out an e-mail alert).
Perhaps this seems like a contrived example, but that is actually my point; you can't treat a TransactionScope as a "black box". The scope is in fact a dependency like any other; TransactionScope just provides a convenient abstraction for a unit of work that may not always be appropriate because it doesn't actually wrap a database connection and can't predict the future. In particular, it's normally not appropriate when a single logical operation needs to span more than one database connection, whether those connections are to the same database or different ones. It tries to handle this case of course, but as you've already learned, the result is sub-optimal.
The way I see it, you have a few different options:
Make explicit the fact that Method1 and Method2 require a connection by having them take a connection parameter, or by refactoring them into a class that takes a connection dependency (constructor or property). This way, the connection becomes part of the contract, so Method1 no longer knows too much - it knows exactly what it's supposed to know according to the design.
Accept that your DoOperation method does have an awareness of what Method1 and Method2 do. In fact, there is nothing wrong with this! It's true that you don't want to be relying on implementation details of some future call, but forward dependencies in the abstraction are generally considered OK; it's reverse dependencies you need to be concerned about, like when some class deep in the domain model tries to update a UI control that it has no business knowing about in the first place.
Use a more robust Unit of Work pattern (also: here). This is getting to be more popular and it is, by and large, the direction Microsoft has gone in with Linq to SQL and EF (the DataContext/ObjectContext are basically UOW implementations). This sleeves in well with a DI framework and essentially relieves you of the need to worry about when transactions start and end and how the data access has to occur (the term is "persistence ignorance"). This would probably require significant rework of your design, but pound for pound it's going to be the easiest to maintain long-term.
Hope one of those helps you.

Categories

Resources