最后一次递归方法检查

时间:2011-10-20 12:31:31

标签: c# recursion queue

我有一个递归方法,可以构建资源及其相关资源的树状结构。

对于我使用的每个资源,我将它添加到一个类成员列表中,我会检查每次迭代,以确保我们不会在相互依赖的资源上无限循环。

每次我第一次调用这个递归方法时,我都需要明确类成员列表。

目前我有一个单独的方法来执行此操作,我可以在调用递归方法之间调用。

我想摆脱这种方法调用并每次自动重置列表。

目前,我可以看到两个解决此问题的方法:

  1. 测试调用方法是否与当前相同 执行方法,如果没有,重置列表
  2. 取而代之的是递归和队列项,出列和 我们去的时候会入队。在方法调用结束时,我可以重置列表。
  3. 你会如何解决这个问题?你会采取什么方法?

    以下是我的代码目前的样子:

    public class GetAllRelatedResourcesByParentGuidQuery : IGetAllRelatedResourcesByParentGuidQuery
        {
            private readonly IList<Guid> _itemsCheckedForRelations = new List<Guid>();
    
            public IEnumerable<IDependency> Invoke(Guid parentCiId, 
                                                      IResoucesByIdQuery getResources)
            {
                if (!_itemsCheckedForRelations.Contains(parentCiId))
                {
                    var relatedResources = getResources.Invoke(parentCiId);
    
                    _itemsCheckedForRelations.Add(parentCiId);
    
                    if (relatedResources.Count() > 0)
                    {
                        foreach (var relatedResource in relatedResources)
                        {
                            relatedResource.Resource.DependentResources = Invoke(
                                                             relatedResource.Resource.Id, 
                                                             getResources);
    
                            yield return relatedResource;
                        }
                    }
                }
            }
    
            public void ResetCheckedItemsCollection()
            {
                _itemsCheckedForRelations.Clear();
            }
        }
    

4 个答案:

答案 0 :(得分:3)

我会创建一个执行创建的 public 方法,但不要理会递归方法,并将其作为参数。

public List<string> DoSomething(int input)
{
    List<string> results = new List<string>();
    DoSomethingImpl(input, results);
    return results;
}

private void DoSomethingImpl(int input, List<T> results)
{
    // For example...
    if (input == 0)
    {
        return results;
    }
    results.Add("Foo");
    DoSomethingImpl(input - 1, results);        
}

答案 1 :(得分:1)

只需调用一个像这样的内部方法的方法:

public class GetAllRelatedResourcesByParentGuidQuery : IGetAllRelatedResourcesByParentGuidQuery 
{ 
        private readonly IList<Guid> _itemsCheckedForRelations = new List<Guid>(); 

        public IEnumerable<IDependency> Invoke(Guid parentCiId,  
                                                  IResoucesByIdQuery getResources) 
        {
            Reset();
            return InternalInvoke(parentCiID, getResources);
        }

        private IEnumerable<IDependency> InternalInvoke(Guid parentCiId,  
                                                  IResoucesByIdQuery getResources) 
        {
             //actual implementation, when going recursive, call this internal method
        }
}

答案 2 :(得分:1)

在我看来,List不应该是类成员,而是您调用的方法的参数...对于此参数,null会发生任何直接调用(甚至可能是默认!)...该方法在这种情况下分配List,在递归调用上它只传递分配的List ...

答案 3 :(得分:0)

您可以尝试使用递归的lambda表达式:

public class GetAllRelatedResourcesByParentGuidQuery :
                    IGetAllRelatedResourcesByParentGuidQuery
{
    public IEnumerable<IDependency> Invoke(
            Guid parentCiId,
            IResoucesByIdQuery getResources)
    {
        var checkedItems = new List<Guid>();
        Func<Guid, IResoucesByIdQuery, IEnumerable<IDependency>> invoke = null;
        invoke = (pcid, gr) =>
        {
            if (!checkedItems.Contains(pcid))
            {
                checkedItems.Add(pcid);
                var drs = gr.Invoke(pcid).ToArray();
                foreach (var relatedResource in drs)
                {
                    relatedResource
                        .Resource
                        .DependentResources =
                            invoke(relatedResource.Resource.Id, gr);
                }
                return drs;
            }
            return Enumerable.Empty<IDependency>();
        };
    }
}

通过这种方法,可以进行多个并发调用,而无需任何特殊逻辑来清除列表。