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.

 

 

Sunday, 14 August 2005 16:45:30 (Eastern Daylight Time, UTC-04:00)
Security Briefs
Thursday, 15 December 2005 17:38:18 (Eastern Standard Time, UTC-05:00)
OK, so how do you fix this?

I've tried:

For Each oChild As DirectoryEntry In IISSite.Children
Try
'Debug.WriteLine(String.Format(" Found a child '{0}' '{1}'", oChild.Name, oChild.SchemaClassName))
If String.Compare(oChild.Name, "ROOT", True) = 0 AndAlso String.Compare(oChild.SchemaClassName, IIS_WEB_VIRTUAL_DIR, True) = 0 Then
If oChild.Properties.Contains("AppPoolID") Then
sAppPool = DirectCast(oChild.Properties("AppPoolID").Value, String)
Else
sAppPool = "Unknown"
End If
Exit For
End If
Catch ex As Exception
Finally
If Not oChild Is Nothing Then
oChild.Close()
oChild.Dispose()
oChild = Nothing
End If
End Try
Next


But this still leaks....

Comments are closed.