web-dev-qa-db-ja.com

誰でもIEnumerableとIEnumeratorを私に説明できますか?

誰でもIEnumerableとIEnumeratorを私に説明できますか?

たとえば、foreachでいつ使用するか? IEnumerableとIEnumeratorの違いは何ですか?なぜ使用する必要があるのですか?

237
prodev42

たとえば、foreachでいつ使用するか?

IEnumerable "over" foreachは使用しません。 IEnumerableを実装すると、foreachpossibleが使用されます。

次のようなコードを書くとき:

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

機能的には次の記述と同等です。

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

「機能的に同等」とは、実際にコンパイラがコードを変換するものであることを意味します。この例のforeachbazを使用することはできませんnlessbazIEnumerableを実装します。

IEnumerableは、bazがメソッドを実装することを意味します

IEnumerator GetEnumerator()

このメソッドが返すIEnumeratorオブジェクトは、メソッドを実装する必要があります

bool MoveNext()

そして

Object Current()

最初のメソッドは、列挙子を作成したIEnumerableオブジェクト内の次のオブジェクトに進み、完了した場合はfalseを返し、2番目のメソッドは現在のオブジェクトを返します。

.Netで反復できるものはすべてIEnumerableを実装します。独自のクラスを構築していて、IEnumerableを実装するクラスからまだ継承していない場合は、foreachを実装して(および新しいIEnumerableメソッドが返す列挙子クラスを作成することで)GetEnumeratorステートメントでクラスを使用可能にすることができます。

240
Robert Rossney

IEnumerableおよびIEnumeratorインターフェイス

既存の.NETインターフェイスを実装するプロセスの調査を開始するために、まずIEnumerableとIEnumeratorの役割を見てみましょう。 C#がforeachという名前のキーワードをサポートしていることを思い出してください。これにより、任意の配列タイプのコンテンツを反復処理できます。

// 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構造を使用してGarageオブジェクトのサブアイテムを反復処理すると便利です。

// 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();
   }
}

悲しいことに、コンパイラは、GarageクラスがGetEnumerator()という名前のメソッドを実装していないことを通知します。このメソッドは、System.Collections名前空間内に潜んでいるIEnumerableインターフェイスによって形式化されています。この動作をサポートするクラスまたは構造は、含まれるサブアイテムを呼び出し元に公開できることを通知します(この例では、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()、Current、およびReset()のカスタマイズされたバージョンを提供することは確かに自由ですが、より簡単な方法があります。 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);

ただし、IEnumerableの機能をオブジェクトレベルから非表示にする場合は、明示的なインターフェイス実装を使用するだけです。

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

そうすることで、カジュアルオブジェクトユーザーはGarageのGetEnumerator()メソッドを見つけることができなくなりますが、foreachコンストラクトは必要に応じてバックグラウンドでインターフェイスを取得します。

Pro C#5.0および.NET 4.5 Frameworkからの適応

136
Jahan

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...
}

とにかく違いです。

57
core

類推+コードウォークスルーによる説明

最初にコードなしで説明し、それから後で追加します。

航空会社を経営しているとしましょう。そして、各飛行機では、飛行機で飛んでいる乗客についての情報を知りたいです。基本的には、飛行機を「横断」できるようにしたいです。言い換えると、フロントシートから出発して、飛行機の後方に向かって進み、乗客に情報を尋ねます。彼らは誰なのか、どこから来たのか、などです。飛行機でしかできません。 、 もしそれが:

  1. 可算
  2. カウンターがある場合。

これらの要件はなぜですか?それがインターフェースに必要なものだからです。

これが情報過多の場合、知っておく必要があるのは、飛行機の各乗客に最初から始めて最後まで進むための質問をいくつかできるようにすることです。

countableはどういう意味ですか?

航空会社が「可算」である場合、これは飛行機に乗務員が存在しなければならないことを意味します。乗務員の唯一の仕事はカウントです。この乗務員は非常に具体的な方法でカウントする必要があります。

  1. カウンター/フライトアテンダントは、最初の乗客の前に(安全をデモする全員の正面、救命胴衣の着用方法などで)開始しなければなりません。
  2. 彼/彼女(つまり客室乗務員)は、通路を「次へ」移動して最初の座席に移動する必要があります。
  3. 次に、記録する必要があります:(i)その人が座席に座っている人、および(ii)通路の彼らの現在の位置。

カウント手順

航空会社のキャプテンは、すべての乗客が調査またはカウントされた時点でのレポートを求めています。したがって、最初の席の人に話しかけた後、客室乗務員/カウンターは機長に報告し、報告が与えられると、カウンターは通路での彼/彼女の正確な位置を記憶し、彼/彼女が去った場所で右に数え続けますオフ。

このようにして、船長は常に調査対象の現在の人物に関する情報を持つことができます。そうすれば、この個人がマンチェスターシティが好きだとわかったら、その乗客に優遇措置などを与えることができます。

  • カウンターは、飛行機の終点に達するまで進み続けます。

これをIEnumerablesと結びましょう

  • 列挙型は、飛行機の乗客の集まりです。民間航空法-これらは基本的にすべてのIEnumerablesが従わなければならない規則です。航空会社のアテンダントが乗客情報をキャプテンに行くたびに、基本的に乗客をキャプテンに「譲歩」します。キャプテンは基本的に乗客と一緒に何でもできます-乗客を飛行機に再配置することを除いて。この場合、マンチェスターシティをフォローしている場合、彼らは優遇されます(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)
    

概要

言い換えると、にカウンターがあれば、何かをカウントできます。カウンタは(基本的に)必要があります:(i)その場所を記憶します(state)、(ii) next、(iii)に移動し、彼が扱っているcurrent人について知る。

Enumerableは、 "countable"の単なる高級な言葉です。つまり、enumerableを使用すると、「列挙」(つまり、カウント)できます。

46
BKSpurgeon

IEnumerable GetEnumeratorを実装します。呼び出されると、そのメソッドは、MoveNext、Reset、およびCurrentを実装する IEnumerator を返します。

したがって、クラスがIEnumerableを実装するとき、メソッド(GetEnumerator)を呼び出して、foreachなどのループで使用できる新しいオブジェクト(IEnumerator)を取得できると言っています。

22
DavGarcia

IEnumerableを実装すると、リストのIEnumeratorを取得できます。

IEnumeratorでは、yieldキーワードを使用して、リスト内のアイテムへのforeachスタイルの順次アクセスが可能です。

Foreach実装の前(たとえばJava 1.4)、リストを反復する方法は、リストから列挙子を取得し、リスト内の「次の」項目を要求することでした。次のアイテムとして返される値はnullではありません。 foreachは、lock()が舞台裏でMonitorクラスを実装するのと同じように、単に言語機能として暗黙的にそれを行います。

ForeachはIEnumerableを実装しているため、リストで機能することを期待しています。

17
Neil Barnwell
  • IEnumerableを実装するオブジェクトは、他の人が各アイテムにアクセスできるようにします(列挙子による)
  • IEnumeratorを実装するオブジェクトが反復を実行しています。列挙可能なオブジェクトをループしています。

リスト、スタック、ツリーのような列挙可能なオブジェクトを考えてください。

15

IEnumerableおよびIEnumerator(およびそれらに対応する汎用のIEnumerable <T>およびIEnumerator <T>)は、 。Iterator。Net Framework Class Libray collections の実装のベースインターフェイスです。

IEnumerableは、ほとんどのコードで見られる最も一般的なインターフェイスです。 foreachループ、ジェネレーター(yieldなど)を有効にし、その小さなインターフェイスのために、緊密な抽象化を作成するために使用されます。 IEnumerableはIEnumeratorに依存

一方、IEnumeratorは、やや低レベルの反復インターフェイスを提供します。これは explicit iterator と呼ばれ、プログラマーが反復サイクルをより細かく制御できるようにします。

IEnumerable

IEnumerableは、それをサポートするコレクションの繰り返し処理を可能にする標準インターフェイスです(実際、今日考えられるすべてのコレクションタイプはIEnumerableを実装しています)。コンパイラーのサポートにより、foreachなどの言語機能が可能になります。一般的に、これはこれを有効にします 暗黙的なイテレータの実装

foreachループ

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

foreachループは、IEnumerableインターフェイスを使用する主な理由の1つだと思います。 foreachの構文は非常に簡潔で、さまざまな変数をチェックして実行内容を確認する必要があるループの従来のCスタイルと比較すると、非常にわかりやすいです。

yieldキーワード

おそらくあまり知られていない機能は、IEnumerableyield returnおよびyield breakステートメントを使用して C#のジェネレーター を有効にすることです。

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

抽象化

実際のもう1つの一般的なシナリオは、IEnumerableを使用して最小限の抽象化を提供することです。これは非常に小さく読み取り専用のインターフェースであるため、コレクションをIEnumerableとして公開することをお勧めします(たとえばListではなく) )。そうすれば、クライアントのコードを壊さずに実装を自由に変更できます(たとえば、ListをLinkedListに変更します)。

ガッチャ

留意すべき動作の1つは、ストリーミング実装(たとえば、最初にすべての結果をメモリにロードする代わりにデータベースから行ごとにデータを取得する)で、コレクションに対してcannot反復することです一回以上。これは、Listのようなメモリ内コレクションとは対照的であり、問​​題なく複数回繰り返すことができます。 ReSharperは、たとえば、 IEnumerableの可能な複数の列挙のコード検査があります です。

IEnumerator

一方、IEnumeratorは、IEnumerble-foreach-magicを機能させる舞台裏のインターフェイスです。厳密に言えば、明示的な反復子を有効にします。

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

私の経験では、IEnumeratorは、より冗長な構文とわずかに混乱したセマンティクスのために、一般的なシナリオではめったに使用されません(少なくとも私にとっては、例えばMoveNext()も値を返しますが、名前ではまったく示唆されていません)。

IEnumeratorの使用例

私はIEnumeratorのみを使用しました(特に低レベルの)ライブラリとフレームワークIEnumerableインターフェイスを提供していました。 1つの例は、さまざまなファイルストリームとシリアル化を使用して背後でデータが収集されたにもかかわらず、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;   
    }
}
11
ziya

IEnumerableの実装は、本質的に、オブジェクトを反復処理できることを意味します。特定のリストにはインデックスを作成できませんが、列挙できるので、必ずしも配列であるとは限りません。

IEnumeratorは、反復の実行に使用される実際のオブジェクトです。リスト内のあるオブジェクトから次のオブジェクトへの移動を制御します。

ほとんどの場合、IEnumerableおよびIEnumeratorは、foreachループの一部として透過的に使用されます。

8
Dan Herbert

IEnumerableとIEnumeratorの違い:

  • IEnumerableはIEnumeratorを内部的に使用します。
  • IEnumerableは、どのアイテム/オブジェクトが実行されているかを知りません。
  • IEnumeratorを別の関数に渡すたびに、アイテム/オブジェクトの現在の位置がわかります。
  • IEnumerableコレクションを別の関数に渡すたびに、アイテム/オブジェクトの現在の位置がわかりません(どのアイテムが実行されているかわかりません)

    IEnumerableには1つのメソッドGetEnumerator()があります

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

IEnumeratorには、1つのプロパティcurrentと2つのメソッドResetおよびMoveNextがあります(リスト内のアイテムの現在の位置を知るのに役立ちます)。

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

Iteratorパターンを理解しておくと役立ちます。同じものを読むことをお勧めします。

イテレータパターン

高レベルでは、反復子パターンを使用して、あらゆるタイプのコレクションを反復処理する標準的な方法を提供できます。イテレータパターンには、実際のコレクション(クライアント)、アグリゲータ、イテレータの3人の参加者がいます。集約は、イテレータを返すメソッドを持つインターフェース/抽象クラスです。 Iteratorは、コレクションを反復処理できるメソッドを持つインターフェイス/抽象クラスです。

パターンを実装するには、まずイテレータを実装して、関連するコレクション(クライアント)を反復処理できる具象を生成する必要があります。次に、コレクション(クライアント)はアグリゲータを実装して、上記のイテレータ。

UMLダイアグラムは次のとおりです Iterator Pattern

したがって、基本的にc#では、IEnumerableは抽象集計であり、IEnumeratorは抽象Iteratorです。 IEnumerableには、目的のタイプのIEnumeratorのインスタンスを作成する単一のメソッドGetEnumeratorがあります。リストのようなコレクションは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++;
            }
        }

ご不明な点がございましたら、お気軽にお問い合わせください。

4
lalatnayak

IEnumerableは、Ienumeratorを含むボックスです。 IEnumerableは、すべてのコレクションの基本インターフェイスです。コレクションがIEnumerableを実装している場合、foreachループが動作します。以下のコードでは、独自の列挙子を持つステップを説明しています。コレクションを作成するClassを最初に定義します。

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

ここで、クラスCustomerのコレクションとして機能するClassを定義します。インターフェイスIEnumerableを実装していることに注意してください。そのため、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();

        }
    }
3
Amir

マイナーな貢献。

それらの多くは、「いつ使用するか」と「foreachで使用する」について説明しています。ここで別のStates Differenceを、IEnumerableとIEnumeratorの両方の違いについての質問に応じて追加することを考えました。

以下のディスカッションスレッドに基づいて、以下のコードサンプルを作成しました。

IEnumerable、IEnumerator vs foreach、whatを使用するタイミングIEnumeratorとIEnumerableの違いは何ですか?

Enumeratorは、関数呼び出し間の状態(反復位置)を保持しますが、Enumerableの反復は保持しません。

理解するためのコメント付きのテスト済みの例を次に示します。

専門家は私を追加/修正してください。

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());
    }
}
2
Sai

私はこれらの違いに気づきました:

A.リストをさまざまな方法で繰り返します。foreachはIEnumerableに、whileループはIEnumeratorに使用できます。

B. IEnumeratorは、あるメソッドから別のメソッドに渡すときに現在のインデックスを記憶できます(現在のインデックスで動作を開始します)が、IEnumerableはインデックスを記憶できず、インデックスを先頭にリセットします。このビデオの詳細 https://www.youtube.com/watch?v=jd3yUjGc9M

2
RotatingWheel

IEnumerableIEnumeratorはどちらもC#のインターフェイスです。

IEnumerableは、IEnumeratorインターフェイスを返す単一のメソッドGetEnumerator()を定義するインターフェイスです。

これは、IEnumerableforeachステートメントで使用できることを実装するコレクションへの読み取り専用アクセスで機能します。

IEnumeratorには、MoveNextResetの2つのメソッドがあります。また、Currentというプロパティがあります。

以下に、IEnumerableとIEnumeratorの実装を示します。

1
Jihed Jaoidi
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
  */
0
Md Shahriar