IEnumerator<T>를 반환하는 메서드를 갖고 이를 foreach 루프에서 사용할 수 있나요?

StackOverflow https://stackoverflow.com/questions/3315

문제

내 양식의 모든 텍스트 상자 높이를 설정해야 하며 그 중 일부는 다른 컨트롤 내에 중첩되어 있습니다.나는 다음과 같은 일을 할 수 있다고 생각했습니다.

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() 방법?

도움이 되었습니까?

해결책

컴파일러에서 알려준 대로 반환 유형을 IEnumerable로 변경해야 합니다.이것이 항복 반환 구문이 작동하는 방식입니다.

다른 팁

다시 한번 확인하기 위해

private static IEnumerator<TextBox> FindTextBoxes(Control rootControl)

변경 사항

private static IEnumerable<TextBox> FindTextBoxes(Control rootControl)

그게 전부입니다 :-)

IEnumerator를 반환하면 해당 메서드를 호출할 때마다 다른 열거자 개체가 됩니다(반복할 때마다 열거자를 재설정하는 것처럼 작동).IEnumerable을 반환하면 foreach는 항복 문이 있는 메서드를 기반으로 열거할 수 있습니다.

// 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 메서드는 다음 중 무엇이든 허용합니다. 또는 허용 가능한 반환 유형을 고려합니다. GetEnumerator, 다음에서 사용할 수 있는 것을 반환합니다. foreach.매개변수가 IEnumerator<> 응답은 IEnumerable<T>, 전화를 걸어도 GetEnumerator 일단 그것에는 나쁜 결과가 나올 가능성이 높습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top