2014-01-25 58 views
1

this問題有一個遞歸函數找到父更換尾遞歸調用:試圖通過一個循環

public static T FindParent<T>(DependencyObject child) where T : DependencyObject 
{ 
    DependencyObject parentObject = VisualTreeHelper.GetParent(child); 
    if (parentObject == null) return null; 
    var parent = parentObject as T; 
    if (parent != null) 
    { 
     return parent; 
    } 
    return FindParent<T>(parentObject); 
} 

ReSharper的提供我將其轉換爲一個循環,而不是遞歸,但它確實像即:

public static T FindParent<T>(DependencyObject child) where T : DependencyObject 
{ 
    while (true) 
    { 
     DependencyObject parentObject = VisualTreeHelper.GetParent(child); 
     if (parentObject == null) return null; 
     var parent = parentObject as T; 
     if (parent != null) 
     { 
      return parent; 
     } 
     child = parentObject; 
    } 
} 

現在我有一個崩潰膨脹組及其所有子組的功能:

不幸的是整形器不提供我把它轉換像一個:(

private void MenuItemCollapseAll_OnClick(object sender, RoutedEventArgs e) 
{ 
    // ... truncated for brievety 
    IEnumerable<CollectionViewGroup> groups = grid.Items.Groups.OfType<CollectionViewGroup>().ToArray(); 
    CollapseGroups(grid, groups); 
} 

public void CollapseGroups(DataGridControl grid, IEnumerable<CollectionViewGroup> groups) 
{ 
    foreach (var @group in groups) 
    { 
     grid.CollapseGroup(group); 
     var subGroups = @group.Items.OfType<CollectionViewGroup>().ToArray(); 
     if (subGroups.Any()) 
     { 
      CollapseGroups(grid, subGroups); 
     } 
    } 
} 

以上我只是無法弄清楚如何將它轉換中使用while聲明中以同樣的方式,不能完全肯定是否有可能爲了這個功能。

任何想法?

+1

無需'如果(subGroups.Any()){摺疊組(網格,子組); } - 只需調用CollapseGroups。如果subGroups數組爲空,則該方法將立即退出。如果你非常關心效率,而不想不必要地調用方法,那麼你應該使用if(subGroups.Length == 0)而不是使用Any的擴展方法。 – phoog

+0

好的,謝謝! – Aybe

回答

3

這不是尾遞歸。遞歸調用在foreach循環的另一個迭代之後。但是,並非所有的希望都失去了。

你可以做些什麼來將它轉換爲迭代是做一個Stack<Tuple<DataGridControl, IEnumerable<CollectionViewGroup>>並用遞推一個新的元組到堆棧上來取代遞歸調用。然後循環,直到堆棧耗盡。

但首先,我注意到第一個參數從不改變。所以迭代版本實際上並不需要保留的堆棧:

public void CollapseGroups(DataGridControl grid, IEnumerable<CollectionViewGroup> groups) 
{ 
    var to_process = new Stack<IEnumerable<CollectionViewGroup>>(); 
    to_process.Push(groups); 
    do { 
     groups = to_process.Pop(); 
     foreach (var @group in groups) 
     { 
      grid.CollapseGroup(@group); 
      to_process.Push(@group.Items.OfType<CollectionViewGroup>()); 
     } 
    } while (to_process.Count > 0); 
} 
+0

太棒了,謝謝! :))) – Aybe