Udostępnij za pośrednictwem


Tworzenie klasy Visual C# do użycia w instrukcji foreach

W tym artykule pokazano, jak używać IEnumerable interfejsów i IEnumerator do tworzenia klasy, której można użyć w instrukcji foreach .

Oryginalna wersja produktu: Visual Studio
Oryginalny numer KB: 322022

IEnumerator, interfejs

IEnumerable i IEnumerator są często używane razem. Chociaż te interfejsy są podobne (i mają podobne nazwy), mają różne cele.

Interfejs IEnumerator zapewnia iteracyjne możliwości kolekcji, która jest wewnętrzna dla klasy. IEnumerator wymaga zaimplementowania trzech metod:

  • Metoda MoveNext , która zwiększa indeks kolekcji o 1 i zwraca wartość logiczną wskazującą, czy koniec kolekcji został osiągnięty.

  • Metoda Reset , która resetuje indeks kolekcji do początkowej wartości -1. Spowoduje to unieważnienie modułu wyliczającego.

  • Metoda Current , która zwraca bieżący obiekt pod adresem position.

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

IEnumerable, interfejs

Interfejs IEnumerable zapewnia obsługę foreach iteracji. IEnumerable wymaga zaimplementowania GetEnumerator metody .

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

Kiedy używać interfejsu

Początkowo może się okazać, że korzystanie z tych interfejsów jest mylące. Interfejs IEnumerator zapewnia iterację obiektu typu kolekcji w klasie. Interfejs IEnumerable zezwala na wyliczanie przy użyciu foreach pętli. GetEnumerator Jednak metoda interfejsu IEnumerable zwraca IEnumerator interfejs. Aby zaimplementować IEnumerablemetodę , należy również zaimplementować .IEnumerator Jeśli nie zaimplementujesz IEnumeratormetody , nie możesz rzutować wartości zwracanej z GetEnumerator metody IEnumerable na IEnumerator interfejs.

Podsumowując, użycie IEnumerable klasy wymaga zaimplementowania IEnumeratorklasy . Jeśli chcesz zapewnić obsługę programu foreach, zaimplementuj oba interfejsy.

Przykład krok po kroku

W poniższym przykładzie pokazano, jak używać tych interfejsów. W tym przykładzie IEnumerator interfejsy i IEnumerable są używane w klasie o nazwie cars. Klasa cars ma wewnętrzną tablicę car obiektów. Aplikacje klienckie mogą wyliczać za pomocą tej tablicy wewnętrznej przy użyciu foreach konstrukcji ze względu na implementację tych dwóch interfejsów.

  1. Wykonaj następujące kroki, aby utworzyć nowy projekt aplikacja konsolowa w programie Visual C#:

    1. Uruchom program Microsoft Visual Studio .NET lub Visual Studio.
    2. W menu Plik wskaż polecenie Nowy, a następnie kliknij Projekt.
    3. Kliknij Projekty Visual C# w sekcji Rodzaje projektów, a następnie kliknij Aplikacja konsoli w sekcji Szablony.
    4. W polu Nazwa wpisz ConsoleEnum.
  2. Zmień nazwę Class1.cs na host.cs, a następnie zastąp kod w host.cs następującym kodem:

    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. W menu Projekt kliknij pozycję Dodaj klasę, a następnie wpisz samochód w polu Nazwa.

  4. Zastąp kod w car.cs następującym kodem:

    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. W menu Projekt kliknij pozycję Dodaj klasę, aby dodać kolejną klasę do projektu, a następnie wpisz samochody w polu Nazwa.

  6. Zastąp kod w cars.cs następującym kodem:

    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. Uruchamianie projektu.

Następujące dane wyjściowe są wyświetlane w oknie Konsola :

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

Najlepsze rozwiązania

Przykład w tym artykule jest możliwie najprostszy, aby lepiej wyjaśnić użycie tych interfejsów. Aby kod był bardziej niezawodny i upewnić się, że kod korzysta z bieżących wytycznych dotyczących najlepszych rozwiązań, zmodyfikuj kod w następujący sposób:

  • Zaimplementuj IEnumerator w zagnieżdżonej klasie, aby można było utworzyć wiele modułów wyliczających.
  • Podaj obsługę wyjątków IEnumeratordla Current metody . Jeśli zawartość kolekcji ulegnie zmianie, wywoływana reset jest metoda . W związku z tym bieżący moduł wyliczający jest unieważniany i otrzymujesz IndexOutOfRangeException wyjątek. Inne okoliczności mogą również spowodować ten wyjątek. Dlatego zaimplementuj blok, Try...Catch aby przechwycić ten wyjątek i zgłosić InvalidOperationException wyjątek.
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);
      }
    }
}