簡體   English   中英

PrincipalSearchResult <T> 自動處理其集合中的所有元素?

[英]Does PrincipalSearchResult<T> automatically dispose all elements in its collection?

在MSDN文檔中找不到任何關於此的內容。

也就是這樣做,說:

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

這是我見過的大多數例子,或者我應該這樣做:

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

后者(在迭代期間明確地處理每個項目)看起來“更安全” - 即符合指南以明確處理所有IDisposable對象 - 但它有點凌亂; 例如,它排除了使用LINQ迭代搜索結果。

回應@Rup的評論:

你可以編寫一個從父迭代器返回一個結果的yield迭代器

是的,我認為這樣可以啟用LINQ。 像下面的擴展方法:

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

可以用作:

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

但這有必要嗎?

通常情況下,在許多情況下,不調用Dispose()不會導致大問題:寫得好的一次性對象將實現在終結器中清理所需的相同邏輯。 (免責聲明:我不是說“不要召喚處理”:這是有原因的!例如,終結可能會發生很多次。我只是在描述這里的后果)。

但是,AD對象是一個值得注意的例外; 特別是, SearchResultCollection因此問題而聞名(參考:MSDN(類文檔和其他文章)和Active Directory:設計,部署和運行Active Directory )。 似乎由於技術原因,無法在其終結器中釋放資源,因此不調用dispose將導致內存泄漏。

正如Scott和Joe所指出的,許多MSDN示例都沒有對集合中的項目進行dispose調用; 但是,前Windows Azure技術布道者Ryan Dunn是“目錄服務編程.NET開發人員指南”的共同作者,他建議使用此博客文章中的每個項目調用dispose。 從帖子:

通常,始終在以下對象類型上顯式調用Dispose():

  • 的DirectoryEntry
  • SearchResultCollection(來自.FindAll())
  • DirectorySearcher(如果您尚未明確設置SearchRoot)

我相信這是你對“權威來源”最接近的; 我的個人意見是:

  • 如果可以,請撥打電話。 它不會有任何不好,特別是如果你可以使用Joe的擴展方法獲得LINQ功能
  • 去使用reflector / ilspy / ildasm和/或像dotTrace這樣的內存配置文件來真正看到發生了什么(基本上,Scott已經做了什么,但更深入)

我最初來到網站問同樣的問題,但是看到你的問題讓我有動機打破ILSpy並弄清楚自己是否真的這樣做了。

首先搜索結果的dispose功能:

// System.DirectoryServices.AccountManagement.PrincipalSearchResult<T>
public void Dispose()
{
    if (!this.disposed)
    {
        if (this.resultSet != null)
        {
            lock (this.resultSet)
            {
                this.resultSet.Dispose();
            }
        }
        this.disposed = true;
    }
}

從那里我檢查了resultSet.Dispose() (在我的例子中,resultSet是一個ADDNLinkedAttrSet

// System.DirectoryServices.AccountManagement.ADDNLinkedAttrSet
public override void Dispose()
{
    try
    {
        if (!this.disposed)
        {
            if (this.primaryGroupMembersSearcher != null)
            {
                this.primaryGroupMembersSearcher.Dispose();
            }
            if (this.queryMembersResults != null)
            {
                this.queryMembersResults.Dispose();
            }
            if (this.currentMembersSearcher != null)
            {
                this.currentMembersSearcher.Dispose();
            }
            if (this.memberSearchResults != null)
            {
                this.memberSearchResults.Dispose();
            }
            if (this.memberSearchersQueue != null)
            {
                foreach (DirectorySearcher directorySearcher in this.memberSearchersQueue)
                {
                    directorySearcher.Dispose();
                }
                this.memberSearchersQueue.Clear();
            }
            IDisposable disposable = this.members as IDisposable;
            if (disposable != null)
            {
                disposable.Dispose();
            }
            IDisposable disposable2 = this.membersEnum as IDisposable;
            if (disposable2 != null)
            {
                disposable2.Dispose();
            }
            if (this.membersQueue != null)
            {
                foreach (IEnumerable enumerable in this.membersQueue)
                {
                    IDisposable disposable3 = enumerable as IDisposable;
                    if (disposable3 != null)
                    {
                        disposable3.Dispose();
                    }
                }
            }
            if (this.foreignGroups != null)
            {
                foreach (GroupPrincipal groupPrincipal in this.foreignGroups)
                {
                    groupPrincipal.Dispose();
                }
            }
            this.disposed = true;
        }
    }
    finally
    {
        base.Dispose();
    }
}

你可以看到foreach循環在它所擁有的所有成員上進行迭代。 所以它正在為每個成員為你做Dispose。

所以,是的,它確實處置了所有成員,然后是一些成員。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM