2011-10-20 35 views
2

我有一种递归方法,可以构建资源及其相关资源的树状结构。递归方法检查的最后一次迭代

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

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

目前我有一个独立的方法来做到这一点,我可以调用递归方法调用。

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

此刻,我能看到两个选项来解决这个问题:

  1. 测试调用的方法是否相同,目前 执行的方法,如果没有,重置列表
  2. 摆脱递归和队列项目,而不是队列中的排队队列和队列队列。在方法调用结束时,我可以重置列表。

你将如何去解决这个问题?你会采取什么方法?

这里是我的代码目前的样子:

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(); 
     } 
    } 
+1

如果您粘贴部分代码可能有助于理解您的推理。 在你的场景中,我认为最好有2个重载方法:一个用于第一个调用和第二个,它是递归的,由第一个调用。 –

+0

有些代码会有帮助。 AFAIK,如果没有返回语句和对象作为参数传递,递归是无效的,在这个参数上执行动作,并且这个对象必须随着每次递归而改变。 – hungryMind

+0

谢谢你们。我已经在上面包含了我的代码。 –

回答

3

我会做它执行创建公共方法,但使递归方法不在意,并把它作为一个参数。

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);   
} 
+0

那不叫过载一个方法;) – Polity

+0

@Polity:真。将编辑:) –

+0

谢谢乔恩。那很完美。现在看起来很明显。 –

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 
     } 
} 
1

在我看来,该List不应该是一个类的成员,但你调用方法的参数...任何直接调用与null发生此参数(甚至可以是一个默认的!)......的方法分配在这种情况下List和递归调用它只是通过分配List ...

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>(); 
     }; 
    } 
} 

采用这种方法多并发呼叫可以在没有任何特殊的逻辑来清除列表中进行选择。