Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
422 views
in Technique[技术] by (71.8m points)

.net - Does PrincipalSearchResult<T> automatically dispose all elements in its collection?

Can't find anything in the MSDN documentation on this.

I.e. is it enough to do, say:

using(PrincipalSearcher searcher = ...)
{
    foreach (var principal in searcher.FindAll())
    {
        ... do something ...
    } // The PrincipalSearchResult<T> returned by searcher.FindAll is disposed here
}

which is what most examples I've seen do, or should I do:

using(PrincipalSearcher searcher = ...)
{
    foreach(var principal in searcher.FindAll())
    {
        using (principal)
        {
            // ... do something ...
        }
    } 
}

The latter (explicitly disposing each item during iteration) looks "safer" - i.e. conforms to the guideline to explicitly dispose all IDisposable objects - but it's a bit messy; for example, it precludes the use of LINQ to iterate over search results.

In response to @Rup's comment:

you could write a yield iterator that returned one result from the parent iterator

Yes, I think that would work to enable LINQ. Something like the following extension method:

public static IEnumerable<T> EnumerateAndDispose<T>(this IEnumerable<T> collection) where T : IDisposable
{
    foreach (T item in collection)
    {
        using (item)
        {
            yield return item;
        }
    }
}

which can be used as:

searcher.FindAll().EnumerateAndDispose().Select(... use LINQ ...)

But is it necessary?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Generally speacking, in many cases, not calling Dispose() will not cause big problems: well written disposable objects will implement the same logic needed to clean things up in the finalizer. (Disclaimer: I'm not saying "do not call dispose": it is there for a reason! For example, Finalization can happen a lot later. I'm only describing what are the consequences here).

However, AD objects are a notable exception; in particular, SearchResultCollection is known for suffering from this problem (references: MSDN (both the class docs and other articles), and Active Directory: Designing, Deploying, and Running Active Directory). It seems that for technical reasons it is not possible to release resources in its finalizer, so not calling dispose will lead to memory leaks.

As pointed out by Scott and Joe, many MSDN examples do not call dispose on the items in the collection; however, Ryan Dunn, former Windows Azure Technical Evangelist and co-author of the The .NET Developers Guide to Directory Services Programming, recommends to use to call dispose on each item in this blog post. From the post:

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

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

This is the closest you can have to an "authoritative source", I believe; however my personal opinion is:

  • if you can, do call dispose. It will not make any bad, especially if you can get back LINQ functionality with Joe's extension method
  • go and use reflector/ilspy/ildasm AND/OR a memory profile like dotTrace to really see what is going on (basically, what Scott already did, but going deeper)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...