IEnumerator<T> を返すメソッドを用意し、それを foreach ループで使用できますか?
-
08-06-2019 - |
質問
フォーム上のすべてのテキストボックスの高さを設定する必要があります。その一部は他のコントロール内にネストされています。次のようなことができると思いました:
private static IEnumerator<TextBox> FindTextBoxes(Control rootControl)
{
foreach (Control control in rootControl.Controls)
{
if (control.Controls.Count > 0)
{
// Recursively search for any TextBoxes within each child control
foreach (TextBox textBox in FindTextBoxes(control))
{
yield return textBox;
}
}
TextBox textBox2 = control as TextBox;
if (textBox2 != null)
{
yield return textBox2;
}
}
}
次のように使用します。
foreach(TextBox textBox in FindTextBoxes(this))
{
textBox.Height = height;
}
しかし、もちろんコンパイラはダミーを吐き出します。 フォーリーチ を期待しています IEnumerable ではなく I列挙子.
別のクラスを作成せずにこれを行う方法はありますか? GetEnumerator() 方法?
解決
コンパイラの指示に従って、戻り値の型を IEnumerable に変更する必要があります。これが、yield return 構文の仕組みです。
他のヒント
明確にするために
private static IEnumerator<TextBox> FindTextBoxes(Control rootControl)
への変更
private static IEnumerable<TextBox> FindTextBoxes(Control rootControl)
これですべてのはずです:-)
IEnumerator を返す場合、そのメソッドを呼び出すたびに異なる列挙子オブジェクトになります (反復ごとに列挙子をリセットしたかのように動作します)。IEnumerable を返す場合、foreach は yield ステートメントを使用したメソッドに基づいて列挙できます。
// Generic function that gets all child controls of a certain type,
// returned in a List collection
private static List<T> GetChildTextBoxes<T>(Control ctrl) where T : Control{
List<T> tbs = new List<T>();
foreach (Control c in ctrl.Controls) {
// If c is of type T, add it to the collection
if (c is T) {
tbs.Add((T)c);
}
}
return tbs;
}
private static void SetChildTextBoxesHeight(Control ctrl, int height) {
foreach (TextBox t in GetChildTextBoxes<TextBox>(ctrl)) {
t.Height = height;
}
}
列挙子が与えられ、それを for-each ループで使用する必要がある場合は、以下を使用してそれをラップできます。
static public class enumerationHelper { public class enumeratorHolder<T> { private T theEnumerator; public T GetEnumerator() { return theEnumerator; } public enumeratorHolder(T newEnumerator) { theEnumerator = newEnumerator;} } static enumeratorHolder<T> toEnumerable<T>(T theEnumerator) { return new enumeratorHolder<T>(theEnumerator); } private class IEnumeratorHolder<T>:IEnumerable<T> { private IEnumerator<T> theEnumerator; public IEnumerator<T> GetEnumerator() { return theEnumerator; } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return theEnumerator; } public IEnumeratorHolder(IEnumerator<T> newEnumerator) { theEnumerator = newEnumerator; } } static IEnumerable<T> toEnumerable<T>(IEnumerator<T> theEnumerator) { return new IEnumeratorHolder<T>(theEnumerator); } }
の toEnumerable
メソッドはそれをすべて受け入れます c# または ああ 受け入れ可能な戻り値の型を考慮します GetEnumerator
, で使用できるものを返します。 foreach
. 。パラメータが IEnumerator<>
応答は IEnumerable<T>
, 、電話しているのに GetEnumerator
一度実行すると悪い結果が生じる可能性があります。
所属していません StackOverflow