Lorsque vous voulez énumérer récursive un objet hiérarchique, sélectionner certains éléments en fonction de certains critères, il existe de nombreux exemples de techniques comme « aplatissement » puis filtrer en utilisant Linq: comme ceux qu'on trouve ici:Énumération des collections qui ne sont pas intrinsèquement IEnumerable?
Mais, lorsque vous énumérez quelque chose comme la collection Controls d'un formulaire, ou la collection Nodes d'un TreeView, j'ai été incapable d'utiliser ces types de techniques car elles semblent nécessiter un argument (à la méthode d'extension) qui est un IEnumerable collection: transmettre dans SomeForm.Controls ne compile pas.
La chose la plus utile que j'ai trouvé ceci:
qui ne vous donne une méthode d'extension pour Control.ControlCollection avec un résultat IEnumerable vous pouvez utiliser avec LINQ.
J'ai modifié l'exemple ci-dessus pour analyser les nœuds d'un TreeView sans problème.
public static IEnumerable<TreeNode> GetNodesRecursively(this TreeNodeCollection nodeCollection)
{
foreach (TreeNode theNode in nodeCollection)
{
yield return theNode;
if (theNode.Nodes.Count > 0)
{
foreach (TreeNode subNode in theNode.Nodes.GetNodesRecursively())
{
yield return subNode;
}
}
}
}
C'est le genre de code que je vous écris en utilisant maintenant la méthode d'extension:
var theNodes = treeView1.Nodes.GetNodesRecursively();
var filteredNodes =
(
from n in theNodes
where n.Text.Contains("1")
select n
).ToList();
Et je pense qu'il peut y avoir une façon plus élégante de le faire où la contrainte (s) sont Ce que je veux savoir s'il est possible de définir de telles procédures génériquement, de sorte que: lors de l'exécution, je puisse transmettre le type de collection, ainsi que la collection réelle, à un paramètre générique, le code est donc indépendant de si c'est un TreeNodeCollection ou Controls.Collection .
Il serait également intéressant de savoir s'il existe un autre moyen (moins cher? Fastser?) Que celui montré dans le deuxième lien (ci-dessus) pour obtenir un TreeNodeCollection ou Control.ControlCollection sous une forme utilisable par Linq.
Un commentaire de Leppie à propos de 'SelectMany dans le post SO lié au premier (ci-dessus) semble être un indice.
Mes expériences avec SelectMany ont été: bien, appelez-les "catastrophes". :)
Appréciez les pointeurs. J'ai passé plusieurs heures à lire tous les messages postaux que je pouvais trouver sur ces sujets, et je me frayais un chemin dans un exotica tel que le "y-combinator". Une expérience « leçon d'humilité », je pourrais ajouter :)
Dans "selector (item) .OfType()" le OfType n'est pas obligatoire, car il devrait déjà renvoyer T. –
Non c'est obligatoire car le sélecteur renvoie un IEnumerable et non et IEnumerable. –
mrydengren
Oh, je vois le problème maintenant. J'ai mis à jour le code pour refléter les changements. Bonne prise. – mrydengren