是否PrincipalSearchResult 自动出售其集合中的所有元素?(Does Pri

2019-06-24 16:45发布

找不到这个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的评论:

你可以写从父迭代器返回一个结果的迭代器产量

是的,我认为这工作,使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 ...)

但是,有必要吗?

Answer 1:

一般来说speacking,在许多情况下,不调用Dispose()不会造成大问题:良好的书面一次性对象将实行清理东西的终结需要相同的逻辑。 (免责声明:我不是说“不叫处理”:这是有原因的。例如,定稿会发生很多后来我只描述什么是这里的后果)。

然而,AD对象是一个显着的例外; 特别是, SearchResultCollection是著名的从这个问题的痛苦(参考:MSDN(类文档都和其他物品),以及Active Directory的:设计,部署和运行Active Directory )。 看来,由于技术原因,不可能以释放其终结的资源,所以不调用dispose会导致内存泄漏。

正如斯科特和乔指出,很多MSDN示例不调用Dispose集合中的物品; 不过,瑞恩·邓恩,前Windows Azure的技术专家和在.NET开发人员指南目录服务编程的合着者,建议使用来调用部署在每个项目上这个博客帖子 。 从帖子:

在一般情况下,始终明确对以下对象类型调用Dispose():

  • 的DirectoryEntry
  • SearchResultCollection(从.FindAll())
  • 的DirectorySearcher(如果你还没有明确设置SearchRoot)

这是你可以有一个“权威人士”最近,我相信; 但是我个人的意见是:

  • 如果可以的话,就调用处理。 它不会让任何不好的,特别是如果你能找回LINQ功能与乔的扩展方法
  • 去使用反射/ ilspy /反汇编和/或类似的存储配置文件dotTrace真正看到正在发生的事情(基本上,斯科特已经做了,但不断深入)


Answer 2:

我最初来到现场问同样的问题,但看到你的问题给了我动力爆发ILSpy ,弄清自己,如果它不这样做。

首先,搜索结果的处置功能:

// 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循环在那里itterating在它拥有的所有成员。 因此,它是做处置你的每个部件上。

所以,是的,它不处理所有成员的,然后一些。



文章来源: Does PrincipalSearchResult automatically dispose all elements in its collection?