2017-10-13 30 views
1

我想创建一个linq像扩展方法来从层次结构像树一样获取所有项目。使用嵌套的泛型没有很多的代码

这是我的分机

public static List<T> GetAllRecursive<T, TU>(this IList<T> list, Func<T, TU> func) where TU : IEnumerable<T> { 
     var allList = new List<T>(); 
     var toAdd = list.ToList(); 
     while(true) { 
      allList.AddRange(toAdd); 
      var childs = toAdd.SelectMany(x => func(x)).ToList(); 
      if(childs.Count == 0) { 
       return allList; 
      } 
      toAdd = childs; 
     } 
    } 

我这样称呼它

var allGuidelines = Guidelines.GetAllRecursive(x => (IEnumerable<MachineGuidelineTreeItemViewModel>)x.Children);

我怎样才能改善这个梅索德所以我不需要投,每次我用这个?

在此先感谢

+0

孩子的返回类型是什么? –

+0

,你为什么需要将它转换为IEnumerable呢?是不是x.Children IEnumerable <>已经?它是一个更通用的类型,例如,IEnumerable 或类似的东西?如果是这样,你怎么知道把它转换成IE 是安全的? – quetzalcoatl

+0

孩子是一个BindableCollection horotab

回答

1

您可以删除TU类型参数,并在IEnumerable使用OfType代替:

public static List<T> GetAllRecursive<T>(this IList<T> list, Func<T, IEnumerable> func) { 
    var allList = new List<T>(); 
    var toAdd = list.ToList(); 
    while(true) { 
     allList.AddRange(toAdd); 
     var childs = toAdd.SelectMany(x => func(x).OfType<T>()).ToList(); 
     if(childs.Count == 0) { 
      return allList; 
     } 
     toAdd = childs; 
    } 
} 

这种方法是比较宽松的,因为它可以让你通过返回鱼龙混杂功能项目,用方法按类型过滤它。

+0

我想也许'toAdd'变量和'childs'变量在需要时并不一定是'List's。可能不会有很大的区别,但我认为有可能避免在分配'childs'时调用'ToList()'... – BurnsBA

+1

@BurnsBA我同意,确实有一些空间让这种方法更加一般。我与OP的实现一起解决了一个特定的缺点,同时保留了其他代码。 – dasblinkenlight

+0

多数民众赞成正是我正在寻找现在我有一个小电话:'var allGuidelines = Guidelines.GetAllRecursive(x => x.Children);' - 谢谢 – horotab