Thursday, 23 June 2005

A quick reminder on Dispose and foreach

Keith points out today that the foreach loop does not actually call Dispose() on the items being enumerated – only on the enumerator itself.  That is actually news to me – I was always under the assumption that Dispose() would be called on the iterated object when it left scope.

Why should you care?  For anyone programming System.DirectoryServices, this actually has a big impact.  Consider the following, very common code:

        DirectoryEntry entry = new DirectoryEntry(
            "LDAP://dc=mydomain,dc=com",
            null,
            null,
            AuthenticationTypes.Secure
            );
 
        using (entry)
        {
            foreach(DirectoryEntry child in entry.Children)
            {
                //do something
            }
        }

Whoops, we have potentially many undisposed DirectoryEntry objects here.  Given that the SDS namespace has a couple problems with leaking memory, we always recommend you Dispose() your objects in SDS.  This will not do it for you (and no, the ‘entry’ will not call Dispose() for its children either here).

In general, always explicitly call Dispose() on the following object types:

  • DirectoryEntry
  • SearchResultCollection (from .FindAll())
  • DirectorySearcher (if you have not explicitly set a SearchRoot)

Keep this is mind now with the foreach loops as well.