هل يمكنني الحصول على طريقة لإرجاع 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;
}

لكن بالطبع المترجم يبصق دميته، لأنه com.foreach يتوقع ان لا يحصى بدلا من 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