階層オブジェクトを再帰的に列挙し、いくつかの基準に基づいていくつかの要素を選択する場合、「フラット化」してから Linq を使用してフィルタリングするなどの手法の例が多数あります。
しかし、Form の Controls コレクションや TreeView の Nodes コレクションのようなものを列挙する場合、IEnumerable である (拡張メソッドへの) 引数が必要なように見えるため、これらの種類の手法を使用できませんでした。 collection : SomeForm.Controls を渡すとコンパイルされません。
私が見つけた最も有用なものはこれでした:
これにより、Linq で使用できる IEnumerable の結果を持つ Control.ControlCollection の拡張メソッドが得られます。
上記の例を変更して、TreeView のノードを問題なく解析しました。
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;
}
}
}
}
これは、拡張メソッドを使用して現在書いている種類のコードです。
var theNodes = treeView1.Nodes.GetNodesRecursively();
var filteredNodes =
(
from n in theNodes
where n.Text.Contains("1")
select n
).ToList();
そして、制約が渡される場所でこれを行うためのよりエレガントな方法があるかもしれないと思います.
そのようなプロシージャをジェネリックに定義できるかどうかを知りたいので、実行時にコレクションのタイプと実際のコレクションをジェネリックパラメーターに渡すことができるため、コードはかどうかに依存しませんそれは TreeNodeCollection または Controls.Collection です。
また、Linq で使用できる形式で TreeNodeCollection または Control.ControlCollection を取得するために、2 番目のリンク (上記) に示されている方法よりも他の方法 (安い? 速い?) があるかどうかも知りたいと思います。
最初にリンクされた SO 投稿 (上記) の「SelectMany」に関する Leppie のコメントは、手がかりのようです。
SelectMany を使った私の実験は次のとおりです。:)
ポインタに感謝します。私は数時間を費やして、これらの領域に触れている SO の投稿をすべて読み、「y コンビネーター」などの異国情緒をとりとめのない道を歩んできました。「謙虚な」経験、私は付け加えるかもしれません:)