foreach 문에서 Visual C# 클래스를 사용할 수 있도록 만들기

이 문서에서는 및 IEnumerator 인터페이스를 사용하여 IEnumerable 문에서 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 반복을 foreach 지원합니다. IEnumerable 에서는 메서드를 구현해야 합니다 GetEnumerator .

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

어떤 인터페이스를 사용해야 하는가?

처음에는 이러한 인터페이스를 사용하는 것이 혼란스러울 수 있습니다. 인터페이스는 IEnumerator 클래스의 컬렉션 형식 개체를 반복합니다. 인터페이스는 IEnumerable 루프를 사용하여 열거형을 허용합니다 foreach . 그러나 인터페이스의 메서드는 GetEnumeratorIEnumerable 인터페이스를 반환합니다 IEnumerator . 따라서 를 구현 IEnumerable하려면 도 구현 IEnumerator해야 합니다. 를 구현IEnumerator하지 않으면 의 메서드 IEnumerable 에서 GetEnumerator 인터페이스로 반환 값을 캐스팅할 IEnumerator 수 없습니다.

요약하면 를 사용 IEnumerable 하려면 클래스가 를 구현 IEnumerator해야 합니다. 에 대한 foreach지원을 제공하려면 두 인터페이스를 모두 구현합니다.

단계별 예제

다음 예제에서는 이러한 인터페이스를 사용하는 방법을 보여 줍니다. 이 예제 IEnumerator 에서 및 IEnumerable 인터페이스는 라는 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. 프로젝트 메뉴에서 클래스 추가를 클릭한 다음 이름 상자에 car를 입력합니다.

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