2014-01-25 57 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