views:

39

answers:

2

I'm currently writing a piece of code that does some searches which returns IDisposable objects (DirectoryEntry to be specific from an ADAM instance) and I end up with code similar to

using(var entry = (from result in results
                   let  entry = result.GetDirectoryEntry()
                   where entry != null
                   select entry).Last())
{
  //blah blah
}

but who is then responsible for Disposing the objects not returned by the above query? or more to the point is the above code actually missing a call to Dispose() for all other entries than the last?

+3  A: 

if it is Linq to Objects then you are responsible. Yes, objects will not be disposed. You should take the results of query before Last and Dispose them manually.

Andrey
I have never seen an example of code that tmanually disposes Linq objects. The garbage collector cleans up the objects eventually, and unless you have something like a long-running unmanaged process behind the Linq query, manual disposal should not be necessary.
Robert Harvey
Only if the code actually implements a finalizer. IF there isn't a finalizer implemented then the resources will really leak. Not to mention this results in a) Resources not being disposed ASAP and b) Promotion of objects into the longer garbage collection queue which can have performance impacts if you are allocating and destroying a lot of objects with finalizers.
Spence
A good disposer should do it's job and then call GC.SuppressFinalize(this);
Spence
@Robert Harvey you have never seen it, because usually they are not `IDisposable`
Andrey
+1: Also, there is no guarentee the GC will ever run (therefore, no guarentee finalisers will run), and even if it does, you may very well run out of what ever resource should be disposed before the GC needs to collect memory.
Binary Worrier
+1  A: 

The dispose is based on the data context. The query itself is pure .Net and will not require a disposer, unless you create objects that require disposing. In which case you would need to individually call the disposer on all objects that you call.

I don't think that using linq in this situation is going to be suitable as you are going to leak resources. AFAIK they are working on a linq to active directory provider, but until then you will probably be better off trying to write your query directly to AD.

Or you can write a loop to deal with the resources:

DirectoryEntry entry = null;
foreach(var result in results)
{
   //Need to add logic to deal with errors.
   var temp = result.GetDirectoryEntry();
   if (temp != null)
   {
       if (entry != null)
       {
            entry.Dispose();
            entry = temp;
       }
       else  
       {
           entry = temp;
       }
   }
}   
using (entry)
{
    //code here
}

BTW you should see this entry under MSDN GetDirectoryEntry: Calling GetDirectoryEntry on each SearchResult returned through DirectorySearcher can be slow.

Spence