There is a certain base class representing a node of an element tree:

class TreeITem { public bool Enabled {get;set;} } 

E has two of his heirs: a regular node and a directory (which has ITreeItem type ITreeItem ). In general, it turns out something like folders and files.

File class:

 class FileItem : TreeItem { ... } 

Folder class:

 class FolderItem : TreeItem { .... public Collection<ITreeItem> SubItems {get;set;} } 

And ultimately we will work with the TreeItem collection:

 Collection<TreeItem> AllItems 

The question is: how to find all instances inherited by TreeItem in AllItems with, say, the Enabled == true field Enabled == true using LINQ ? I tried using SelectMany , but something does not work at all - I take out the elements of the first and second level, but it does not go any further.

In general, the question boils down to how to pull this tree into the list, and there it is no problem to find one of them by condition. Interests option through LINQ

  • > The question is: how can I find all instances inherited by TreeItem in AllItems with, say, the Enabled field == true? The question is not very clear what exactly you need. Judging by this formulation, you need this lambda: AllItems.Where (x => x.Enabled) - DreamChild
  • @DreamChild, such a lambda will find only all the elements of the first level. And in the first level (as in the rest) there can be an item of the FolderItem type, and in turn, there is also a collection of sub-elements, and there can also be a FolderItem . Duck, I want to get them all - Donil
  • @Donil no, I did not offer you this lambda, I wanted to ask you to formulate your question more clearly - DreamChild
  • Ummm ... I do not even know what to add. In general, present a tree of elements. An item can be of type FileItem (it has no children) or FolderItem (it can have elements like FileItem or FolderItem ) and so on. So I want to get all the elements, regardless of the level of nesting. So clearer? Find all the files and folders in the directory where the field Enabled = true no matter how deeply they lie - this is if you have an anology with files / folders - Donil
  • one
    You can look at [here] [1] and [here] [2]. [1]: blog.zwezdin.com/ru/101 [2]: weblogs.asp.net/okloeten/archive/2006/07/09/… - Freezze

1 answer 1

There is a certain complexity, so implementation exclusively using LINQ is hardly possible (let them correct me if I am mistaken). The fact is that your structure is a tree, and therefore its crawling should be done using recursion. And recursion implies the rejection of anonymous functions, since an anonymous function cannot call itself, since it is anonymous.

I can offer something like:

 // ваш TreeItem, никаких изменений public class TreeITem { public bool Enabled { get; set; } } // тут тоже все по-прежнему public class FileItem : TreeITem { } public class FolderItem : TreeITem { public Collection<TreeITem> SubItems { get; set; } // это свойство заполнено содержимым для иллюстрации работы // как можно видеть, есть только 4 удовлетворяющих условию элемента public static Collection<TreeITem> AllItems = new Collection<TreeITem> { new TreeITem { Enabled = true }, new TreeITem(), new FolderItem { SubItems = new Collection<TreeITem> { new TreeITem { Enabled = true }, new TreeITem { Enabled = true }, new TreeITem { Enabled = false }, new TreeITem { Enabled = true }, new FileItem(), new TreeITem() } }, new FileItem(), }; // сама рекурсивная функция private static IList<TreeITem> Select(IEnumerable<TreeITem> source, Func<TreeITem, bool> predicate) { var res = new List<TreeITem>(); foreach (var treeITem in source) { var folder = treeITem as FolderItem; if (folder != null) res.AddRange(Select(folder.SubItems, predicate)); if(predicate(treeITem)) res.Add(treeITem); } return res; } // внешняя обертка а-ля LINQ, работающая через предикат public static IList<TreeITem> Select(Func<TreeITem, bool> predicate) { return Select(AllItems, predicate); } } .... var res = FolderItem.Select(x => x.Enabled); // будет выведено 4 - количество вложенных элементов с Enabled == true Console.WriteLine(res.Count()); 
  • one
    So I couldn’t figure out how to do this with LINQ :) I did it through recursion, but I still think let me ask, you never know. Thanks for the detailed answer! - Donil
  • yet LINQ is not a silver bullet, and not all can be done with it - DreamChild