共用方式為


在 foreach 語句中使用 Visual C# 類別

本文示範如何使用 IEnumerableIEnumerator 介面來建立可在 語句中使用的 foreach 類別。

原始產品版本: Visual Studio
原始 KB 編號: 322022

IEnumerator 介面

IEnumerableIEnumerator 經常一起使用。 雖然這些介面很類似(且有類似的名稱),但它們有不同的用途。

介面 IEnumerator 提供類別內部集合的反覆功能。 IEnumerator 需要您實作三種方法:

  • 方法 MoveNext 會將集合索引遞增 1,並傳回 bool,指出是否已到達集合結尾。

  • 方法,會將 Reset 集合索引重設為其初始值 -1。 這會使列舉值失效。

  • 方法 Current ,這個方法會傳回 位於 position的目前物件。

    public bool MoveNext()
    {
        position++;
        return (position < carlist.Length);
    }
    public void Reset()
    {
        position = -1;
    }
    public object Current
    {
        get { return carlist[position];}
    }
    

IEnumerable 介面

介面 IEnumerable 提供反覆運算的支援 foreachIEnumerable 需要您實作 GetEnumerator 方法。

public IEnumerator GetEnumerator()
{
    return (IEnumerator)this;
}

使用哪一個介面的時機

一開始,您可能會發現使用這些介面會令人困惑。 介面 IEnumerator 會在類別中的集合類型物件上提供反覆專案。 介面 IEnumerable 允許使用 foreach 迴圈列舉。 不過, GetEnumerator 介面的 IEnumerable 方法會傳 IEnumerator 回 介面。 因此,若要實 IEnumerable作 ,您也必須實作 IEnumerator。 如果您未實IEnumerator作 ,則無法將 的傳回值從 GetEnumerator 的 方法IEnumerableIEnumerator轉換成 介面。

總而言之,使用 IEnumerable 會要求 類別實 IEnumerator作 。 如果您想要提供 的支援 foreach,請實作這兩個介面。

逐步說明範例

下列範例示範如何使用這些介面。 在此範例中, IEnumeratorIEnumerable 介面會用於名為 cars的類別中。 類別 cars 具有 對象的內部數位 car 。 用戶端應用程式可以使用 建構來列舉此內部數位,因為這兩個 foreach 介面的實作。

  1. 請遵循下列步驟,在 Visual C# 中建立新的控制台應用程式專案:

    1. 開始Microsoft Visual Studio .NET 或 Visual Studio。
    2. [檔案] 功能表上,指向 [開新檔案] ,然後按一下 [專案]
    3. 按兩下 [項目類型] 下的 [Visual C# 專案],然後按兩下 [範本] 下的 [控制台應用程式]。
    4. 在 [ 名稱] 方塊中,輸入 ConsoleEnum
  2. 將Class1.cs重新命名host.cs,然後使用下列程式代碼取代 host.cs 中的程式代碼:

    using System;
    namespace ConsoleEnum
    {
       class host
       {
           [STAThread]
           static void Main(string[] args)
           {
               cars C = new cars();
               Console.WriteLine("\nInternal Collection (Unsorted - IEnumerable,Enumerator)\n");
               foreach(car c in C)
               Console.WriteLine(c.Make + "\t\t" + c.Year);
               Console.ReadLine();
           }
       }
    }
    
  3. 在 [專案] 功能表上,按兩下 [新增類別],然後在 [名稱] 方塊中輸入汽車

  4. 以下欄程序代碼取代 car.cs 中的程式代碼:

    using System;
    using System.Collections;
    namespace ConsoleEnum
    {
       public class car
       {
           private int year;
           private string make;
           public car(string Make,int Year)
           {
               make=Make;
               year=Year;
           }
           public int Year
           {
               get  {return year;}
               set {year=value;}
           }
           public string Make
           {
               get {return make;}
               set {make=value;}
           }
       }//end class
    }//end namespace
    
  5. 在 [專案] 功能表上,按兩下 [新增類別] 將另一個類別新增至專案,然後在 [名稱] 方塊中輸入汽車

  6. 以下列程式代碼取代 cars.cs 中的程式碼:

    using System;
    using System.Collections;
    namespace ConsoleEnum
    {
        public class cars : IEnumerator,IEnumerable
        {
           private car[] carlist;
           int position = -1;
           //Create internal array in constructor.
           public cars()
           {
               carlist= new car[6]
               {
                   new car("Ford",1992),
                   new car("Fiat",1988),
                   new car("Buick",1932),
                   new car("Ford",1932),
                   new car("Dodge",1999),
                   new car("Honda",1977)
               };
           }
           //IEnumerator and IEnumerable require these methods.
           public IEnumerator GetEnumerator()
           {
               return (IEnumerator)this;
           }
           //IEnumerator
           public bool MoveNext()
           {
               position++;
               return (position < carlist.Length);
           }
           //IEnumerable
           public void Reset()
           {
               position = -1;
           }
           //IEnumerable
           public object Current
           {
               get { return carlist[position];}
           }
        }
      }
    
  7. 執行專案。

下列輸出會出現在 主控台 視窗中:

Ford            1992
Fiat            1988
Buick           1932
Ford            1932
Dodge           1999
Honda           1977

最佳做法

本文中的範例盡可能簡單,以更清楚地說明這些介面的使用方式。 若要讓程式代碼更健全,並確保程式代碼使用目前的最佳做法指導方針,請修改程序代碼,如下所示:

  • 在巢狀類別中實 IEnumerator 作 ,以便您可以建立多個列舉值。
  • 為的方法IEnumerator提供例外狀況處理Current。 如果集合的內容變更,則會 reset 呼叫 方法。 因此,目前的列舉值已失效,而且您會收到 IndexOutOfRangeException 例外狀況。 其他情況也可能造成這個例外狀況。 因此,實作 區塊 Try...Catch 來攔截此例外狀況並引發例外狀況 InvalidOperationException
using System;
using System.Collections;
namespace ConsoleEnum
{
    public class cars : IEnumerable
    {
        private car[] carlist;
  
        //Create internal array in constructor.
        public cars()
        {
            carlist= new car[6]
            {
                new car("Ford",1992),
                new car("Fiat",1988),
                new car("Buick",1932),
                new car("Ford",1932),
                new car("Dodge",1999),
                new car("Honda",1977)
            };
        }
        //private enumerator class
        private class  MyEnumerator:IEnumerator
        {
            public car[] carlist;
            int position = -1;

            //constructor
            public MyEnumerator(car[] list)
            {
                carlist=list;
            }
            private IEnumerator getEnumerator()
            {
                return (IEnumerator)this;
            }
            //IEnumerator
            public bool MoveNext()
            {
                position++;
                return (position < carlist.Length);
            }
            //IEnumerator
            public void Reset()
            {
                position = -1;
            }
            //IEnumerator
            public object Current
            {
                get
                {
                    try
                    {
                        return carlist[position];
                    }
                    catch (IndexOutOfRangeException)
                    {
                        throw new InvalidOperationException();
                    }
                }
            }
        }  //end nested class
      public IEnumerator GetEnumerator()
      {
          return new MyEnumerator(carlist);
      }
    }
}