سؤال
بصرف النظر عن (IEnumerable Returns GetEnumerator() ، يعد IEnumerble ضروريًا لـ "foreach")
تسمح لنا الطريقتان التاليتان تقريبًا بالتكرار على المجموعة
ميزة واحد على الآخر؟
static void Main()
{
IEnumerator<int> em = MyEnumerator<int>(new int[] { 1, 2, 3, 4 });
IEnumerator<int> e = Collection<int>
(new int[] { 1, 2, 3, 4 }).GetEnumerator();
while (em.MoveNext())
{
Console.WriteLine(em.Current);
}
while (e.MoveNext())
{
Console.WriteLine(e.Current);
}
Console.ReadKey(true);
}
النهج 1
public static IEnumerator<T> MyEnumerator<T>(T[] vals )
{
T[] some = vals;
foreach (var v in some)
{
yield return v;
}
}
النهج 2
public static IEnumerable<T> Collection<T>(T[] vals)
{
T[] some = vals;
foreach (var v in some)
{
yield return v;
}
}
المحلول
والفرق الرئيسي هو أن معظم واجهات برمجة التطبيقات (API) تدعم إدخال IEnumerable<T>
ولكن ليس من IEnumerator<T>
.
عليك أيضًا أن تتذكر استدعاء Reset() عند استخدامه بينما يكون بناء الجملة أكثر وضوحًا في IEnumerable<T>
(اتصل وحسب GetEnumerator
مرة أخرى).راجع أيضًا تعليق إريك ليبر حول كون إعادة التعيين فكرة سيئة؛إذا لم يتم تنفيذ إعادة التعيين في ملفك IEnumerator<T>
أو أنه أصبح عدادًا لمرة واحدة فقط (عديم الفائدة جدًا في كثير من الحالات).
قد يكون الاختلاف الآخر هو أنه يمكن أن يكون لديك IEnumerable<T>
التي يمكن تعدادها من عدة سلاسل رسائل في نفس الوقت ولكن IEnumerator<T>
قم بتخزين موضع واحد في البيانات المذكورة (تخيل أ RandomEnumerable
أو RangeEnumerable
).
لذا فإن الاستنتاج هو ذلك IEnumerable<T>
أكثر تنوعًا، ولكن على أي حال إذا كان لديك وظيفة ترجع ملف IEnumerator<T>
توليد IEnumerable<T>
من حوله بسيط.
class EnumeratorWrapper<T> : IEnumerable<T>
{
Func<IEnumerator<T>> m_generator;
public EnumeratorWrapper(Func<IEnumerator<T>> generator)
{
m_generator = generator;
}
public IEnumerator<T> GetEnumerator()
{
return m_generator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return m_generator();
}
}
فقط من أجل تناسق واجهة برمجة التطبيقات (API) باستخدام IEnumerable<T>
يبدو الحل الأفضل بالنسبة لي.
لكن المشكلة مع Reset()
في IEnumerator<T>
اجعله حلاً غير قابل للاستخدام على أي حال، لذلك IEnumerable<T>
هو الطريق للذهاب.
نصائح أخرى
صححني إذا كنت مخطئًا ولكن الفرق الوحيد هو الفرق بين IEnumerable و IEnumerator وبما أنك قلت على وجه التحديد أنك لا تسأل عن الفرق، فكلاهما جيد ...