فهم التكرار في C#: استخدام IEnumerator<T>
في حلقات foreach
في C#، يُعتبر التعاون مع المجموعات والتكرار عبر البيانات ممارسة أساسية للمطورين. تثار تساؤلات شائعة عند محاولة إعادة IEnumerator<T>
من طريقة واستخدامه في حلقة foreach
. تصبح هذه المسألة أكثر إثارة للاهتمام عندما تحتاج إلى التنقل عبر عناصر التحكم المتداخلة داخل واجهة المستخدم.
لنغوص في هذه الحالة من خلال استكشاف جوهر المشكلة وتقديم حل عملي.
المشكلة
تخيل أن لديك نموذج Windows حيث تحتاج إلى تعديل ارتفاع عناصر التحكم من نوع TextBox
ديناميكيًا. قد لا تتواجد هذه TextBoxes
فقط في المستوى الجذري للنموذج، ولكن قد يكون بعضها مدمجًا داخل عناصر تحكم أخرى، مما يخلق هيكلًا معقدًا. تريد استخدام طريقة تستخدم yield
لإعادة TextBoxes
التي تم العثور عليها واحدة تلو الأخرى.
قد تبدو طريقة البدء الخاصة بك على النحو التالي:
private static IEnumerator<TextBox> FindTextBoxes(Control rootControl)
{
foreach (Control control in rootControl.Controls)
{
if (control.Controls.Count > 0)
{
// البحث بشكل تكراري عن أي نصوص داخل كل عنصر تحكم فرعي
foreach (TextBox textBox in FindTextBoxes(control))
{
yield return textBox;
}
}
TextBox textBox2 = control as TextBox;
if (textBox2 != null)
{
yield return textBox2;
}
}
}
ومع ذلك، عند استخدام هذه الطريقة داخل حلقة foreach
كما يلي:
foreach(TextBox textBox in FindTextBoxes(this))
{
textBox.Height = height;
}
ستواجه خطأً في المترجم. يحدث هذا الخطأ لأن حلقة foreach
تتوقع IEnumerable
، لكن طريقتك تعيد IEnumerator
.
الحل
تكمن المفتاح لحل هذه المشكلة في تغيير نوع العائد لطريقتك من IEnumerator<T>
إلى IEnumerable<T>
. يسمح لك بناء الجملة yield return
في C# بإنشاء مُكرر بشكل فعّال بدون الحاجة إلى فئة مُعَدٍ منفصلة.
إليك كيفية تعديل طريقتك:
الطريقة المعدلة
private static IEnumerable<TextBox> FindTextBoxes(Control rootControl)
{
foreach (Control control in rootControl.Controls)
{
// التحقق إذا كان هناك أية عناصر تحكم فرعية
if (control.Controls.Count > 0)
{
// البحث بشكل تكراري عن TextBoxes في عناصر التحكم الفرعية
foreach (TextBox textBox in FindTextBoxes(control))
{
yield return textBox;
}
}
// إذا كان عنصر التحكم الحالي هو TextBox، قم بإعادته
if (control is TextBox textBox2)
{
yield return textBox2;
}
}
}
الشرح
-
تغيير نوع العائد: تعيد الطريقة الآن
IEnumerable<TextBox>
بدلاً منIEnumerator<TextBox>
. يعني هذا أنه يمكن استخدامها مباشرة في حلقةforeach
. -
استخدام
yield return
: يوفر استخدامyield return
وسيلة نظيفة وفعّالة لاسترجاع عناصر التحكم من نوعTextBox
أثناء تقدم الحلقة.
مع هذا التغيير، سيعمل استخدام الطريقة في حلقة foreach
بشكل سلس الآن، وسيتم معالجة كل TextBox
بشكل فردي.
الخاتمة
قد يؤدي العمل مع مجموعات C# وحلقات foreach
في بعض الأحيان إلى تحديات غير متوقعة، خاصة عند التعامل مع طرق استدعاء تكرارية وهياكل التحكم. عن طريق تغيير نوع العائد من IEnumerator<T>
إلى IEnumerable<T>
, يمكنك الاستفادة بسهولة من التعداد في تراكيب الحلقات دون التعقيدات الإضافية.
باتباع هذا النهج، لن تتجنب الأخطاء في المترجم فحسب، بل ستعزز أيضًا إمكانية صيانة وقراءة الكود الخاص بك عند إدارة عناصر التحكم المتداخلة في النموذج الخاص بك.
للمزيد من القراءة، تعرف على مفاهيم مثل IEnumerable، IEnumerator، وكلمة yield
لاستغلال إمكانيات التكرار في C# بالكامل.