هل يمكن لأي شخص أن يشرح لي IEnumerable و IEnumerator؟[مغلق]

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

  •  05-09-2019
  •  | 
  •  

سؤال

هل يمكن لأي شخص أن يشرح لي IEnumerable و IEnumerator؟

على سبيل المثال، متى يتم استخدامه خلال foreach؟ما الفرق بين IEnumerable و IEnumerator؟لماذا نحتاج لاستخدامه؟

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

المحلول

على سبيل المثال، متى تستخدمه أكثر من ذلك؟

أنت لا تستخدم IEnumerable "على" foreach. وبعد تنفيذ IEnumerable يجعل استخدام foreach المستطاع.

عند كتابة رمز مثل:

foreach (Foo bar in baz)
{
   ...
}

انها تعادل وظيفيا لكتابة:

IEnumerator bat = baz.GetEnumerator();
while (bat.MoveNext())
{
   bar = (Foo)bat.Current
   ...
}

عن طريق "مكافئ وظيفيا"، أعني أن هذا هو في الواقع ما يحول المحول البرمجي. لا يمكنك استخدام foreach على baz في هذا المثال ما لم baz تنفذ IEnumerable.

IEnumerable يعني أن baz ينفذ الطريقة

IEnumerator GetEnumerator()

ال IEnumerator الاعتراض على أن هذه الطريقة تعود يجب تنفيذ الأساليب

bool MoveNext()

و

Object Current()

الطريقة الأولى التقدم إلى الكائن التالي في IEnumerable الكائن الذي أنشأ العداد، والعودة false إذا تم ذلك، فإن الثانية ترجع الكائن الحالي.

أي شيء في .NET التي يمكنك تكرار الأدوات IEnumerable. وبعد إذا كنت تبني فصلك الخاص، فلن يرث بالفعل من فئة تنفذ IEnumerable, ، يمكنك جعل صفك قابل للاستخدام في foreach البيانات عن طريق التنفيذ IEnumerable (ومن خلال إنشاء فئة عدادا جديدة GetEnumerator سوف تعود الطريقة).

نصائح أخرى

واجهات IEnumerable و IEnumerator

للبدء في فحص عملية تنفيذ واجهات .NET الحالية ، دعونا نلقي نظرة أولاً على دور ienumerable و ienumerator.أذكر أن C# يدعم كلمة رئيسية سميت ForeAck تتيح لك التكرار على محتويات أي نوع من نوع الصفيف:

// Iterate over an array of items.
int[] myArrayOfInts = {10, 20, 30, 40};
foreach(int i in myArrayOfInts)
{
   Console.WriteLine(i);
}

على الرغم من أنه قد يبدو أن أنواع الصفيف فقط التي يمكن أن تستفيد من هذا البناء ، إلا أن حقيقة الأمر هي أن أي نوع يدعم طريقة تدعى GetEnumerator () يمكن تقييمها من خلال إنشاء Foreach. لتوضيح ، اتبعني!

لنفترض أن لدينا فئة المرآب:

// Garage contains a set of Car objects.
public class Garage
{
   private Car[] carArray = new Car[4];
   // Fill with some Car objects upon startup.
   public Garage()
   {
      carArray[0] = new Car("Rusty", 30);
      carArray[1] = new Car("Clunker", 55);
      carArray[2] = new Car("Zippy", 30);
      carArray[3] = new Car("Fred", 30);
   }
}

من الناحية المثالية ، سيكون من المناسب التكرار على محودي كائن المرآب باستخدام بنية foreach ، تمامًا مثل مجموعة من قيم البيانات:

// This seems reasonable ...
public class Program
{
   static void Main(string[] args)
   {
      Console.WriteLine("***** Fun with IEnumerable / IEnumerator *****\n");
      Garage carLot = new Garage();
      // Hand over each car in the collection?
      foreach (Car c in carLot)
      {
         Console.WriteLine("{0} is going {1} MPH",
         c.PetName, c.CurrentSpeed);
      }
      Console.ReadLine();
   }
}

للأسف ، يعلمك المترجم أن فئة المرآب لا تنفذ طريقة تدعى GetEnumerator ().تم إضفاء الطابع الرسمي على هذا الأسلوب من خلال واجهة IEnumerable، الموجودة داخل مساحة الاسم System.Collections.تعلن الفصول أو الهياكل التي تدعم هذا السلوك أنها قادرة على فضح المواد الفرعية المحتوية على المتصل (في هذا المثال ، الكلمة الرئيسية foreach نفسها).فيما يلي تعريف واجهة .NET القياسية هذه:

// This interface informs the caller
// that the object's subitems can be enumerated.
public interface IEnumerable
{
   IEnumerator GetEnumerator();
}

كما ترون ، تقوم طريقة getEnumerator () بإرجاع إشارة إلى واجهة أخرى باسم System.Collections.Ienumerator.توفر هذه الواجهة البنية الأساسية للسماح للمتصل باجتياز الكائنات الداخلية الموجودة في الحاوية المتوافقة مع IEnumerable:

// This interface allows the caller to
// obtain a container's subitems.
public interface IEnumerator
{
   bool MoveNext (); // Advance the internal position of the cursor.
   object Current { get;} // Get the current item (read-only property).
   void Reset (); // Reset the cursor before the first member.
}

إذا كنت ترغب في تحديث نوع المرآب لدعم هذه الواجهات ، فيمكنك أن تأخذ الطريق الطويل وتنفيذ كل طريقة يدويًا.على الرغم من أنك بالتأكيد حرة في تقديم إصدارات مخصصة من GetEnumerator () و Movenext () واليار وإعادة التعيين () ، هناك طريقة أبسط.نظرًا لأن النوع System.Array (بالإضافة إلى العديد من فئات المجموعة الأخرى) يطبق بالفعل IEnumerable وIEnumerator، فيمكنك ببساطة تفويض الطلب إلى System.Array كما يلي:

using System.Collections;
...
public class Garage : IEnumerable
{
   // System.Array already implements IEnumerator!
   private Car[] carArray = new Car[4];
   public Garage()
   {
      carArray[0] = new Car("FeeFee", 200);
      carArray[1] = new Car("Clunker", 90);
      carArray[2] = new Car("Zippy", 30);
      carArray[3] = new Car("Fred", 30);
   }
   public IEnumerator GetEnumerator()
   {
      // Return the array object's IEnumerator.
      return carArray.GetEnumerator();
   }
}

بعد تحديث نوع Garage الخاص بك، يمكنك استخدام النوع بأمان داخل بنية C# foreach.علاوة على ذلك، نظرًا لأن طريقة GetEnumerator() قد تم تعريفها بشكل عام، فيمكن لمستخدم الكائن أيضًا التفاعل مع نوع IEnumerator:

// Manually work with IEnumerator.
IEnumerator i = carLot.GetEnumerator();
i.MoveNext();
Car myCar = (Car)i.Current;
Console.WriteLine("{0} is going {1} MPH", myCar.PetName, myCar.CurrentSpeed);

ومع ذلك ، إذا كنت تفضل إخفاء وظائف ienumeript من مستوى الكائن ، فما عليك سوى الاستفادة من تنفيذ الواجهة الصريحة:

IEnumerator IEnumerable.GetEnumerator()
{
  // Return the array object's IEnumerator.
  return carArray.GetEnumerator();
}

من خلال القيام بذلك ، لن يجد مستخدم الكائن غير الرسمي طريقة getEnumerator () من المرآب ، في حين أن بناء foreach سيحصل على الواجهة في الخلفية عند الضرورة.

مقتبس من Pro C# 5.0 و.NET 4.5 Framework

تطبيق IEnumerable يعني فصلك إرجاع كائن iEnumerator:

public class People : IEnumerable
{
    IEnumerator IEnumerable.GetEnumerator()
    {
        // return a PeopleEnumerator
    }
}

تطبيق IEnumerator يعني أن صفك يعيد أساليب وخصائص للتكرار:

public class PeopleEnumerator : IEnumerator
{
    public void Reset()...

    public bool MoveNext()...

    public object Current...
}

هذا هو الفرق على أي حال.

Explanation عبر التشابه + كود تجول

أولا تفسير بدون رمز، ثم سأضيفه في وقت لاحق.

دعنا نقول أنك تقوم بتشغيل شركة طيران. وفي كل طائرة تريد أن تعرف معلومات عن الركاب الطائرة في الطائرة. أساسا تريد أن تكون قادرة على "اجتياز" الطائرة. وبعبارة أخرى، فأنت تريد أن تكون قادرا على البدء في المقعد الأمامي، وبعد ذلك العمل في طريقك نحو الجزء الخلفي من الطائرة، يسأل الركاب بعض المعلومات: من هم، حيث هم، حيث يمكن أن تفعل الطائرة فقط ، اذا كانت:

  1. عد، و
  2. إذا كان لديه عداد.

لماذا هذه المتطلبات؟ لأن هذا ما تتطلب الواجهة.

إذا كان هذا هو الحمل الزائد للمعلومات، فكل ما تحتاج إلى معرفته هو أنك تريد أن تكون قادرا على طلب كل راكب في الطائرة بعض الأسئلة، بدءا من الأول وجعل طريقك إلى آخر.

ماذا يعني العد؟

إذا كانت شركة الطيران "قابلة للعد"، فهذا يعني أنه يجب أن يكون هناك مضيف طيران موجود على متن الطائرة، ومن الوظيفة الوحيدة هي العد - وهذا المضيف الرحلة يجب أن يعول بطريقة محددة للغاية:

  1. يجب أن يبدأ مضيف العداد / الرحلة قبل الراكب الأول (في مقدمة الجميع حيث يقومون بسلامة تجريبية، وكيفية وضع سترة الحياة على الخ).
  2. يجب عليه / هي (أي مضيف الطيران) يجب أن "نقل بعد ذلك" حتى الممر إلى المقعد الأول.
  3. هو / هي ستقدم بعد ذلك: (1) من هو الشخص في المقعد، و (2) موقعهم الحالي في الممر.

إجراءات حساب

يريد قبطان شركة الطيران تقريرا عن كل راكب كما وعندما يتم التحقيق فيه أو عد. لذلك بعد التحدث إلى الشخص في المقعد الأول، فإن مضادفة الرحلة / العداد ثم تقارير إلى القبطان، وعندما يعطى التقرير، يتذكر العداد موقفه الدقيق في الممر ويستمر في حساب الحق في المكان الذي ترك فيه / هي إيقاف.

وبهذه الطريقة، يكون القبطان قادرا دائما على إجراء معلومات عن الشخص الحالي. بهذه الطريقة، إذا اكتشف أن هذا الفرد يحب مانشستر سيتي، فيمكنه أن يعطي هذا المعاملة التفضيلية للركاب وما إلى ذلك.

  • يحتفظ العداد حتى يصل إلى نهاية الطائرة.

دعونا ربط هذا مع ienumibles

  • يعد عدلا مجرد مجموعة من الركاب على متن طائرة. قانون الطيران المدني - هذه هي الأساس القواعد التي يجب أن تتبعها جميعها جميعها. في كل مرة يذهب مضيف شركة الطيران إلى القبطان مع معلومات Passeger، نحن في الأساس "العائد" الراكب إلى القبطان. يمكن أن يفعل القبطان أساسا ما يريده مع الراكب - باستثناء إعادة ترتيب الركاب على متن الطائرة. في هذه الحالة، يتم إعطاؤهم معاملة تفضيلية إذا اتبعوا مانشستر سيتي (UGH!)

    foreach (Passenger passenger in Plane)
    // the airline hostess is now at the front of the plane
    // and slowly making her way towards the back
    // when she get to a particular passenger she gets some information
    // about the passenger and then immediately heads to the cabin
    // to let the captain decide what to do with it
    { // <---------- Note the curly bracket that is here.
        // we are now cockpit of the plane with the captain.
        // the captain wants to give the passenger free 
        // champaign if they support manchester city
        if (passenger.supports_mancestercity())
        {
            passenger.getFreeChampaign();
        } else
        {
            // you get nothing! GOOD DAY SIR!
        }
    } //  <---- Note the curly bracket that is here!
          the hostess has delivered the information 
          to the captain and goes to the next person
          on the plane (if she has not reached the 
          end of the plane)
    

ملخص

بمعنى آخر، شيء يعد عد لديه عداد. وبعد وعليك يجب أن (أساسا): (ط) تذكر مكانها (حالة)، (2) تكون قادرة على الانتقال التالي, ، (3) ومعرفة حاضر الشخص الذي يتعامل معه.

تعداد كلمة واحدة مجرد كلمة خيالية ل "عد". بمعنى آخر، يتيح لك تعداد "تعداد" (أي العد).

ienumerable. تنفذ getenumerator. عند الاتصال، هذه الطريقة ستعود ienumerator. والتي تنفذ movenext، إعادة تعيين والحالية.

وبالتالي، عندما تنفذ الفصل الخاص بك iEnaryerable، فإنك تقول أنه يمكنك استدعاء طريقة (Getenumerator) واحصل على كائن جديد يتم إرجاعه (ienumerator) يمكنك استخدامه في حلقة مثل Foreach.

يتيح لك تطبيق IEnumerable من الحصول على ienumerator للحصول على قائمة.

يسمح iEnumerator بفصل الوصول التسلسلي بالأناقة إلى العناصر الموجودة في القائمة، باستخدام الكلمة الأساسية للعائد.

قبل تنفيذ التنفيذ (في Java 1.4، على سبيل المثال)، كانت الطريقة لتكرار القائمة هي الحصول على عداد من القائمة، ثم اطلب من ذلك عن العنصر "التالي" في القائمة، طالما كانت القيمة التي تم إرجاعها كقادم البند ليس فارغ. يحدث ذلك ببساطة أن ذلك ضمنيا كميزة لغوية، بنفس الطريقة التي تقوم بها القفل () تنفذ فئة الشاشة وراء الكواليس.

أتوقع أن تعمل في القوائم لأنها تنفذ IEnaryerable.

  • كائن ينفذ ienumerable. يسمح للآخرين بزيارة كل من العناصر (بواسطة عداد).
  • كائن ينفذ ienumerator. هو القيام بالتمييز. انها حلقات على كائن غير قابل للتعدي.

فكر في الكائنات العديدة اعتبارا من القوائم والمكدس والأشجار.

ienumerable و ienumerator (ونظرائهم العام iEnumerableu003CT> و ienumerator.u003CT> ) واجهات قاعدة ميتاتر تطبيقات في .NET Framework Class Libay مجموعات.

ienumerable. هي الواجهة الأكثر شيوعا التي سترى في غالبية الشفرة هناك. أنه تمكن من حلقة المولدات (التفكير أثمر) وبسبب واجهاتها الصغيرة، كان يستخدم لخلق تجريدات ضيقة. ienumerable يعتمد على ienumerator.

ienumerator., من ناحية أخرى، يوفر واجهة التكرار منخفضة المستوى قليلا. يشار إليها باسم مزيد صريح مما يعطي مبرمج أكثر السيطرة على دورة التكرار.

ienumerable.

iEnumerable هو واجهة قياسية تتيح التكرار عبر المجموعات التي تدعمها (في الواقع، جميع أنواع المجموعة التي يمكنني التفكير فيها في التنفيذ اليوم ienumerable.). دعم مترجم يسمح بميزات اللغة مثل foreach. وبعد بعبارة عامة، فإنه يتيح ذلك تنفيذ ITERATOR ضمني.

foreach حلقة

foreach (var value in list)
  Console.WriteLine(value);

أظن foreach حلقة هي واحدة من الأسباب الرئيسية لاستخدام ienumerable. واجهات. foreach لديه بناء جملة موجز للغاية وسهلة الفهم جدا بالمقارنة مع الكلاسيكية جيم نمط للحلقات حيث تحتاج إلى التحقق من المتغيرات المختلفة لمعرفة ما كان يفعله.

العائد الكلمة الرئيسية

ربما تكون ميزة أقل شهرة هي أن ienumerable. تمكن أيضا مولدات في ج # بإستخدام yield return و yield break صياغات.

IEnumerable<Thing> GetThings() {
   if (isNotReady) yield break;
   while (thereIsMore)
     yield return GetOneMoreThing();
}

التجريد

السيناريو الشائع آخر في الممارسة تستخدم ienumerable. لتوفير التجريدات أضيق الحدود. لأنها واجهة صغيرة وقراءة فقط، يتم تشجيعك على فضح مجموعاتك ienumerable. (بدلا من قائمة علي سبيل المثال). بهذه الطريقة أحرار في تغيير تطبيقك دون كسر رمز العميل (قائمة التغيير إلى linkedlist. على سبيل المثال).

جوتشا

أحد السلوكيات التي يجب أن تكون على دراية بها هي أنه في تطبيقات تدفق (مثل استرداد صف البيانات حسب الصف من قاعدة بيانات، بدلا من تحميل جميع النتائج في الذاكرة أولا) لك لا تستطيع تكرار فوق المجموعة أكثر من مرة. هذا على النقيض من مجموعات في الذاكرة مثل قائمة, ، حيث يمكنك التكرار عدة مرات دون مشاكل. إعادة عرض، على سبيل المثال، لديه تفتيش رمز ل ممكن التعداد المتعدد من ienumerable.

ienumerator.

IEnumerator، من ناحية أخرى، هو وراء واجهة الكواليس التي تجعل ienumerble-foreach-magic الشغل. بالتحدث بدقة، فإنه يتيح للمقترورات الصريحة.

var iter = list.GetEnumerator();
while (iter.MoveNext())
    Console.WriteLine(iter.Current);

في تجربتي ienumerator. نادرا ما يستخدم في السيناريوهات المشتركة بسبب بناء جملة أكثر من حرفا وسليليات مربكة قليلا (على الأقل بالنسبة لي؛ على سبيل المثال movenext () إرجاع قيمة كذلك، والتي لا يقترح الاسم على الإطلاق).

استخدام القضية ل ienumerator

أنا استخدمت فقط ienumerator. على وجه الخصوص (مستوى أقل قليلا) المكتبات والأطر التي كنت أقدمها ienumerable. واجهات. مثال على ذلك هو مكتبة معالجة دفق البيانات التي توفر سلسلة من الكائنات في foreach حلقة على الرغم من أن بيانات الكواليس تم جمعها باستخدام تدفقات الملفات المختلفة والتسلات.

رمز العميل

foreach(var item in feed.GetItems())
    Console.WriteLine(item);

مكتبة

IEnumerable GetItems() {
    return new FeedIterator(_fileNames)
}

class FeedIterator: IEnumerable {
    IEnumerator GetEnumerator() {
        return new FeedExplicitIterator(_stream);
    }
}

class FeedExplicitIterator: IEnumerator {
    DataItem _current;

    bool MoveNext() {
        _current = ReadMoreFromStream();
        return _current != null;           
    }

    DataItem Current() {
        return _current;   
    }
}

تنفيذ IEnumerable يعني أساسا أن الكائن يمكن تكراره. هذا لا يعني بالضرورة أنه صفيف نظرا لأن هناك قوائم معينة لا يمكن فهرستها ولكن يمكنك تعدادها.

IEnumerator هو الكائن الفعلي المستخدم لأداء التكرارات. يتحكم في الانتقال من كائن إلى التالي في القائمة.

معظم الوقت، IEnumerable & IEnumerator تستخدم بشفافية كجزء من foreach حلقه.

الاختلافات بين ienumerable و ienumerator:

  • ienumerable يستخدم ienumerator داخليا.
  • iEnumerable لا يعرف العنصر / الكائن المنفذ.
  • كلما اجل اجتياز ienumerator إلى وظيفة أخرى، إلا أنه يعرف الوضع الحالي للبند / الكائن.
  • كلما نجمع مجموعة ienumerable إلى وظيفة أخرى، لا يعرف الوضع الحالي للبند / الكائن (لا يعرف العنصر الذي تم تنفيذه)

    ienumerable لها طريقة واحدة getenumerator ()

public interface IEnumerable<out T> : IEnumerable
{
IEnumerator<T> GetEnumerator();
}

يحتوي ienumerator على وظيفة واحدة من العقارات وطرقتين إعادة تعيين و movenext (وهو مفيد لمعرفة الوضع الحالي لعنصر في القائمة).

public interface IEnumerator
{
     object Current { get; }
     bool MoveNext();
     void Reset();
}

سيكون فهم نمط المؤتمر المفيد لك. أوصي بقراءة نفسه.

نمط اختبار للماء

على مستوى عال، يمكن استخدام نمط المؤتمر لتوفير طريقة قياسية للتكرار من خلال مجموعات من أي نوع. لدينا 3 مشاركين في نمط المؤتمر، والجمع الفعلي (العميل)، المجمع والمقتطف. المجموع عبارة عن فئة واجهة / مجردة لها طريقة تعرض مكتور. ITERATOR هو فئة واجهة / مجردة لها أساليب تسمح لنا بتكرار من خلال مجموعة.

من أجل تنفيذ النمط، نحتاج أولا إلى تنفيذ جهاز استئناف لإنتاج ملموسة يمكن أن تكرر أكثر من المجموعة المعنية (العميل)، ثم يقوم المجموعة (العميل) بتنفيذ المجمع لإرجاع مثيل للمقتطف أعلاه.

هنا هو مخطط UMLIterator Pattern

لذلك في الأساس في C #، Ienumerable هو الإجمالي التجريدي و Ienumerator هو جهاز التكرار مجردة. ienumerable لديه طريقة واحدة getenumerator المسؤول عن إنشاء مثيل ienumerator للنوع المطلوب. مجموعات مثل القوائم تنفيذ ienumerable.

مثال. يتيح لنفترض أن لدينا طريقة getPermutations(inputString) يؤدي ذلك إلى إرجاع جميع التباديل لسلسلة وأن الطريقة إرجاع مثيل IEnumerable<string>

من أجل حساب عدد التباديلات، يمكننا أن نفعل شيئا مثل أدناه.

 int count = 0;
        var permutations = perm.getPermutations(inputString);
        foreach (string permutation in permutations)
        {
            count++;
        }

المحول البرمجي C # أكثر أو أقل تحول أعلاه إلى

using (var permutationIterator = perm.getPermutations(input).GetEnumerator())
        {
            while (permutationIterator.MoveNext())
            {
                count++;
            }
        }

إذا كان لديك أي أسئلة، فلا تتردد في السؤال.

ienumerable هو مربع يحتوي على ienumerator. ienumerable هي واجهة قاعدة لجميع المجموعات. Foreach Loop يمكن أن تعمل إذا كانت المجموعة تنفذ IEnumerable. في التعليمات البرمجية أدناه تشرح خطوة وجود عداداتنا الخاصة. يتيح أولا تحديد صفنا الذي سنقوم بإجراء المجموعة.

public class Customer
{
    public String Name { get; set; }
    public String City { get; set; }
    public long Mobile { get; set; }
    public double Amount { get; set; }
}

الآن سنتحدد الفئة التي ستكون بمثابة مجموعة لعملائنا الصف. لاحظ أنه ينفذ الواجهة IEnaryerable. بحيث علينا أن ننفذ طريقة Getenumerator. هذا سيعود العداد مخصص لدينا.

public class CustomerList : IEnumerable
{
    Customer[] customers = new Customer[4];
    public CustomerList()
    {
        customers[0] = new Customer { Name = "Bijay Thapa", City = "LA", Mobile = 9841639665, Amount = 89.45 };
        customers[1] = new Customer { Name = "Jack", City = "NYC", Mobile = 9175869002, Amount = 426.00 };
        customers[2] = new Customer { Name = "Anil min", City = "Kathmandu", Mobile = 9173694005, Amount = 5896.20 };
        customers[3] = new Customer { Name = "Jim sin", City = "Delhi", Mobile = 64214556002, Amount = 596.20 };
    }

    public int Count()
    {
        return customers.Count();
    }
    public Customer this[int index]
    {
        get
        {
            return customers[index];
        }
    }
    public IEnumerator GetEnumerator()
    {
        return customers.GetEnumerator(); // we can do this but we are going to make our own Enumerator
        return new CustomerEnumerator(this);
    }
}

الآن سنقوم بإنشاء عداد مخصص الخاص بنا على النحو التالي. لذلك، علينا أن ننفذ طريقة movenext.

 public class CustomerEnumerator : IEnumerator
    {
        CustomerList coll;
        Customer CurrentCustomer;
        int currentIndex;
        public CustomerEnumerator(CustomerList customerList)
        {
            coll = customerList;
            currentIndex = -1;
        }

        public object Current => CurrentCustomer;

        public bool MoveNext()
        {
            if ((currentIndex++) >= coll.Count() - 1)
                return false;
            else
                CurrentCustomer = coll[currentIndex];
            return true;
        }

        public void Reset()
        {
            // we dont have to implement this method.
        }
    }

الآن يمكننا استخدام حلقة foreach على مجموعتنا مثل أدناه؛

    class EnumeratorExample
    {
        static void Main(String[] args)
        {

            CustomerList custList = new CustomerList();
            foreach (Customer cust in custList)
            {
                Console.WriteLine("Customer Name:"+cust.Name + " City Name:" + cust.City + " Mobile Number:" + cust.Amount);
            }
            Console.Read();

        }
    }

مساهمة بسيطة.

كما يفسر الكثير منهم "عند الاستخدام" و "استخدام مع foreach". فكرت في إضافة آخر فرق الدول هنا كما هو مطلوب في السؤال عن الفرق بين كل من IEnumerable Ienumerator.

لقد قمت بإنشاء عينة التعليمات البرمجية أدناه بناء على مؤشرات ترابط المناقشة أدناه.

ienumerable، ienumerator vs foreach، عندما تستخدم ما ما هو الفرق بين ienumerator و ienumerable؟

يحافظ العداد على الولاية (موقف التكرار) بين مكالمات الوظيفة أثناء التكرار من ناحية أخرى غير قابلة للتنفيذ.

هنا هو المثال الذي تم اختباره مع التعليقات لفهم.

الخبراء يرجى إضافة / تصحيح لي.

static void EnumerableVsEnumeratorStateTest()
{
    IList<int> numList = new List<int>();

    numList.Add(1);
    numList.Add(2);
    numList.Add(3);
    numList.Add(4);
    numList.Add(5);
    numList.Add(6);

    Console.WriteLine("Using Enumerator - Remembers the state");
    IterateFrom1to3(numList.GetEnumerator());

    Console.WriteLine("Using Enumerable - Does not Remembers the state");
    IterateFrom1to3Eb(numList);

    Console.WriteLine("Using Enumerable - 2nd functions start from the item 1 in the collection");
}

static void IterateFrom1to3(IEnumerator<int> numColl)
{
    while (numColl.MoveNext())
    {
        Console.WriteLine(numColl.Current.ToString());

        if (numColl.Current > 3)
        {
            // This method called 3 times for 3 items (4,5,6) in the collection. 
            // It remembers the state and displays the continued values.
            IterateFrom3to6(numColl);
        }
    }
}

static void IterateFrom3to6(IEnumerator<int> numColl)
{
    while (numColl.MoveNext())
    {
        Console.WriteLine(numColl.Current.ToString());
    }
}

static void IterateFrom1to3Eb(IEnumerable<int> numColl)
{
    foreach (int num in numColl)
    {
        Console.WriteLine(num.ToString());

        if (num>= 5)
        {
            // The below method invokes for the last 2 items.
            //Since it doesnot persists the state it will displays entire collection 2 times.
            IterateFrom3to6Eb(numColl);
        }
    }
}

static void IterateFrom3to6Eb(IEnumerable<int> numColl)
{
    Console.WriteLine();
    foreach (int num in numColl)
    {
        Console.WriteLine(num.ToString());
    }
}

لقد لاحظت هذه الاختلافات:

أ. يمكننا أن نقوم بالقائمة بطريقة مختلفة، ويمكن استخدامها ل Ienumerable وبين حلقة Ienumerator.

B. يمكن أن يتذكر ienumerator الفهرس الحالي عندما نمر من طريقة إلى أخرى (تبدأ العمل مع الفهرس الحالي) ولكن لا يمكن أن يتذكر iEnumerable الفهرس وإعادة تعيين الفهرس إلى البداية. أكثر في هذا الفيديو https://www.youtube.com/watch؟v=JD3YUJGC9M0.

IEnumerable و IEnumerator كلاهما واجهات في C #.

IEnumerable هي واجهة تحدد طريقة واحدة GetEnumerator() هذا يعود IEnumerator واجهه المستخدم.

هذا يعمل للوصول للقراءة فقط إلى مجموعة تنفذ ذلك IEnumerable يمكن استخدامها مع foreach بيان.

IEnumerator لديه طريقتين، MoveNext و Reset. وبعد كما أن لديها ممتلكات تسمى Current.

ويبين ما يلي تنفيذ ienumerable و ienumerator.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Enudemo
{

    class Person
    {
        string name = "";
        int roll;

        public Person(string name, int roll)
        {
            this.name = name;
            this.roll = roll;
        }

        public override string ToString()
        {
            return string.Format("Name : " + name + "\t Roll : " + roll);
        }

    }


    class Demo : IEnumerable
    {
        ArrayList list1 = new ArrayList();

        public Demo()
        {
            list1.Add(new Person("Shahriar", 332));
            list1.Add(new Person("Sujon", 333));
            list1.Add(new Person("Sumona", 334));
            list1.Add(new Person("Shakil", 335));
            list1.Add(new Person("Shruti", 336));
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
           return list1.GetEnumerator();
        }
    }



    class Program
    {
        static void Main(string[] args)
        {
            Demo d = new Demo();  // Notice here. it is simple object but for 
                                //IEnumerator you can get the collection data

            foreach (Person X in d)
            {
                Console.WriteLine(X);
            }

            Console.ReadKey();
        }
    }
}
/*
Output : 

Name : Shahriar  Roll : 332
Name : Sujon     Roll : 333
Name : Sumona    Roll : 334
Name : Shakil    Roll : 335
Name : Shruti    Roll : 336
  */
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top