هل يمكنني الحصول على طريقة لإرجاع 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;
}
لكن بالطبع المترجم يبصق دميته، لأنه 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
الطريقة سوف تقبل أي شيء ج # أو vb سيعتبر نوع إرجاع مقبول من GetEnumerator
, ، وإرجاع شيء يمكن استخدامه فيه foreach
.إذا كانت المعلمة IEnumerator<>
سيكون الرد IEnumerable<T>
, ، على الرغم من الدعوة GetEnumerator
على ذلك مرة واحدة من المرجح أن تسفر عن نتائج سيئة.