[英]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)
我相信這是你對“權威來源”最接近的; 但我的個人意見是:
我最初來到網站問同樣的問題,但是看到你的問題讓我有動機打破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.