2008-08-06 13 views
15

フォーム上のすべてのテキストボックスの高さを設定する必要があります。その一部は他のコントロール内にネストされています。このようにそれを使用してIEnumerator <T>を返すメソッドをforeachループで使用できますか?

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; 
} 

しかしforeachのIEnumerableをではなく、を期待するので、もちろん、コンパイラは、そのダミーを吐きますIEnumerator

GetEnumerator()メソッドを使用して別のクラスを作成せずにこれを行う方法はありますか?

+2

実際、 'foreach'は' IEnumerable'を全く期待していません( 'IEnumerable 'もありません)。 'GetEnumerator'メソッドを持つものだけが必要です。そのメソッドは、必ずしも 'IEnumerator'または' IEnumerator 'を返す必要はなく、' MoveNext() 'メソッドと' Current'プロパティを持つものだけを返す必要があります。 – Timwi

答えて

13

コンパイラから通知されるので、戻り値の型をIEnumerableに変更する必要があります。これは、利回りの構文がどのように働くかです。

+6

'yield return 'は* IEnumerable ' *または* IEnumerator 'を返すメソッドで使用できます。 'foreach'ループの' IEnumerator 'は使用できません。 – Timwi

1
// 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; 
    } 
} 
3

あなたがするIEnumeratorを返した場合、それはそれぞれの時間は(あなたが各反復の列挙子をリセットするかのように動作する)、そのメソッドを呼び出す異なる列挙子オブジェクトになります。 IEnumerableを返すと、foreachはyieldステートメントでメソッドに基づいて列挙できます。

9

ちょうどあなたが列挙子を与えられ、そしてFOR-でそれを使用する必要がある場合はすべての:-)

0

でなければなりません

private static IEnumerable<TextBox> FindTextBoxes(Control rootControl) 

private static IEnumerator<TextBox> FindTextBoxes(Control rootControl) 

の変更を明確にします各ループでは、以下を使用してラップすることができます:

 
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メソッドでは、またはは受け入れ可能な戻り値の型をGetEnumeratorとみなし、foreachで使用できるものを返します。パラメータがIEnumerator<>の場合、レスポンスはIEnumerable<T>になりますが、GetEnumeratorを呼び出すと結果が悪くなる可能性があります。

関連する問題