久しぶりに仕事でWindows.Formsのフォーム内すべてのコントロールをまとめて設定する操作が必要になって、再帰処理を自分で考えるのが面倒なので検索したらえらく古いコードが。
ArrayList版(from @IT)
public Control[] GetAllControls(Control top)
{
ArrayList buf = new ArrayList();
foreach (Control c in top.Controls)
{
buf.Add(c);
buf.AddRange(GetAllControls(c));
}
return (Control[])buf.ToArray(typeof(Control));
}
このままでも使えるんだけど、今さらArrayListなんか使いたくないってことでジェネリックコレクションを使うように変更。
Add()をなくしてすべてAddRange()で追加してるので若干高速化してると思う。
ジェネリック版
List<Control> GetAllControls_Generic(Control ctrl)
{
var list = new List<Control>(ctrl.Controls.Cast<Control>());
foreach(Control child in ctrl.Controls.Cast<Control>())
{
list.AddRange(GetAllControls_Generic(child));
}
return list;
}
ここまで書いてるうちに「foreachの中がシンプルになったからLinqにできるのでは?」と思いついてさらにコンパクトに。
Linq版
IEnumerable<Control> GetAllControls_Linq(Control ctrl)
{
IEnumerable<Control> list = ctrl.Controls.Cast<Control>();
return list.Concat(list.SelectMany(child => GetAllControls_Linq(child)));
}
Linq版はワーク配列を作らずシーケンスの連結だけになったのでかなり効率的になりました。(たぶん)