2017-10-13 39 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