2008-08-06 5 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; 
} 

Но, конечно, компилятор выплевывает его соску, потому что Еогеасп ожидает IEnumerable, а не IEnumerator.

Есть ли способ сделать это без создания отдельного класса с методом GetEnumerator()?

+2

На самом деле `foreach` не ожидает` IEnumerable` вообще (а не `IEnumerable `). Он ожидает только то, что имеет метод GetEnumerator. Этот метод, в свою очередь, необязательно должен возвращать `IEnumerator` или` IEnumerator `- ему нужно только вернуть то, что имеет метод MoveNext()` и свойство Current. – Timwi 2010-09-01 14:22:53

ответ

13

Как компилятор говорит вам, вам нужно изменить свой тип возврата на IEnumerable. Вот как работает синтаксис возврата доходности.

+6

`yield return` может использоваться с методами, возвращающими * либо *` IEnumerable `* или *` IEnumerator `. Это только в цикле `foreach`, где` IEnumerator `не может быть использован. – Timwi 2010-09-01 14:20:53

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

Просто для уточнения

private static IEnumerator<TextBox> FindTextBoxes(Control rootControl) 

Изменения

private static IEnumerable<TextBox> FindTextBoxes(Control rootControl) 

Это должно быть все :-)

0

Если вы получаете нумератор, и нужно использовать его в для- в каждом цикле вы можете использовать следующее для его обертывания:

 
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 на нем, скорее всего, будут получены плохие результаты.