ما هي أفضل طريقة لتحويل IEnumerator إلى IEnumerator العامة؟

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

  •  06-07-2019
  •  | 
  •  

سؤال

وأنا أكتب ConfigurationElementCollection مخصص لConfigurationHandler مخصصة في C # .NET 3.5 وأنا الرغبة في فضح IEnumerator باعتباره IEnumerator العامة.

وماذا سيكون أفضل وسيلة لتحقيق ذلك؟

وأنا حاليا باستخدام رمز:

public new IEnumerator<GenericObject> GetEnumerator()
{
  var list = new List();
  var baseEnum = base.GetEnumerator();
  while(baseEnum.MoveNext())
  {
    var obj = baseEnum.Current as GenericObject;
    if (obj != null)
      list.Add(obj);
  }
  return list.GetEnumerator();
}

وهتاف

هل كانت مفيدة؟

المحلول

لا أعتقد أن هناك أي شيء في هذا الإطار، ولكن يمكن بسهولة كتابة واحدة:

IEnumerator<T> Cast<T>(IEnumerator iterator)
{
    while (iterator.MoveNext())
    {
        yield return (T) iterator.Current;
    }
}

ومن المغري لمجرد دعوة Enumerable.Cast<T> من LINQ ومن ثم استدعاء GetEnumerator() على النتيجة - ولكن إذا صفك تنفذ بالفعل IEnumerable<T> وT هو نوع القيمة، التي تقوم بدور لا مرجع سابق، وبالتالي فإن recurses دعوة GetEnumerator() ويلقي StackOverflowException . انها آمنة للاستخدام return foo.Cast<T>.GetEnumerator(); عندما foo هو بالتأكيد <م> مختلفا الكائن (الذي لا يفوض إلى هذا واحد) ولكن على خلاف ذلك، وكنت ربما يكون أفضل حالا باستخدام رمز أعلاه.

نصائح أخرى

وIEnumerable<T> مستمد أصلا من IEnumerable لذلك ليس هناك حاجة للقيام بأي التحويل. يمكنك ببساطة يلقي لها ... حسنا في الواقع انها الضمني لا يلقي لزم الأمر.

IEnumerable<T> enumerable = GetGenericFromSomewhere();
IEnumerable sadOldEnumerable = enumerable;
return sadOldEnumerable.GetEnumerator();

والذهاب العكس ليست أكثر صعوبة مع LINQ:

var fancyEnumerable = list.OfType<GenericObject>();
return fancyEnumerable.GetEnumerator();

ولقد تم تشغيل في نفس المشكلة تجاوز سعة المكدس المذكورة هي بعض من التعليقات. في حالتي كان يرجع ذلك إلى حقيقة أن الدعوة GetEnumerator تحتاج إلى أن تكون لbase.GetEnumerator وإلا فإنك حلقة في إعادة تعريف GetEnumerator الخاصة بك.

وهذه هي التعليمات البرمجية التي تم رمي تجاوز المكدس. استخدام بيان foreach استدعاء نفس الوظيفة GetEnumerator أحاول الزائد:

public new IEnumerator<T> GetEnumerator()
{
    foreach (T type in this)
    {
        yield return type;
    }
}

ولقد انتهى الأمر مع نسخة مبسطة من المقال الأصلي لا تحتاج إلى استخدام حامل القائمة.

public class ElementCollection<T> : ConfigurationElementCollection, IList<T>
    ...
    public new IEnumerator<T> GetEnumerator()
    {
        var baseEnum = base.GetEnumerator();
        while (baseEnum.MoveNext())
        {
            yield return baseEnum.Current as T;
        }
    }
    ...
}

ويمكنك استخدام OfType<T> وCast<T>.

public static IEnumerable Digits()
{
    return new[]{1, 15, 68, 1235, 12390, 1239};
}

var enumerable = Digits().OfType<int>();
foreach (var item in enumerable)
    // var is here an int. Without the OfType<int(), it would be an object
    Console.WriteLine(i);

لتحصل على IEnumerator<T> بدلا من IEnumerable<T> يمكنك جعل مجرد الدعوة إلى GetEnumerator()

var enumerator = Digits().OfType<int>().GetEnumerator();

وهذا يعمل بالنسبة لي.

IEnumerator<DataColumn> columnEnumerator = dt.Columns.Cast<DataColumn>().GetEnumerator();
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top