在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调用;然而,Ryan Dunn,前Windows Azure技术布道师和合着者 .NET开发人员目录服务编程指南,建议用来对每个项目进行处理 这篇博文。从帖子:
通常,始终在以下对象类型上显式调用Dispose():
- 的DirectoryEntry
- SearchResultCollection(来自.FindAll())
- DirectorySearcher(如果您尚未明确设置SearchRoot)
我相信这是你对“权威来源”最接近的; 然而 我的个人意见是:
- 如果可以,请拨打电话。它不会有任何不好,特别是如果你可以使用Joe的扩展方法获得LINQ功能
- 去使用reflector / ilspy / ildasm和/或内存配置文件 dotTrace 真正看到发生了什么(基本上,斯科特已经做了什么,但更深入)
我最初来到网站问同样的问题,但看到你的问题给了我突破的动力 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。
所以,是的它确实处理了所有成员,然后是一些成员。