2011-10-20 75 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>(); 
     }; 
    } 
} 

採用這種方法多併發呼叫可以在沒有任何特殊的邏輯來清除列表中進行選擇。