programing tip

반복기와 열거 자의 구별

itbloger 2020. 11. 1. 17:24
반응형

반복기와 열거 자의 구별


.NET 3.5 작업에 대한 인터뷰 질문은 "반복자와 열거 자의 차이점은 무엇입니까?"입니다.

이것은 LINQ를 사용하여 무엇을 만드는지 등의 핵심적인 차이점입니다.

어쨌든 차이점은 무엇입니까? 인터넷에서 확실한 정의를 찾을 수없는 것 같습니다. 실수하지 마세요. 두 용어의 의미를 찾을 수 있지만 답이 약간 다릅니다. 인터뷰에서 가장 좋은 답변은 무엇입니까?

IMO는 컬렉션을 "반복"하고 열거자는 반복 기능을 제공하지만 호출해야합니다.

또한 yield 키워드를 사용하면 상태를 저장한다고합니다. 이 상태는 정확히 무엇입니까? 이 혜택이 발생하는 예가 있습니까?


반복은 일부 단계를 반복하는 것을 의미하고 열거는 값 모음의 모든 값을 살펴 보는 것을 의미합니다. 따라서 열거에는 일반적으로 어떤 형태의 반복이 필요합니다.

이런 식으로 열거는 단계가 컬렉션에서 값을 가져 오는 곳을 반복하는 특별한 경우입니다.

"보통"에 유의하십시오. 열거도 재귀 적으로 수행 될 수 있지만 재귀와 반복은 매우 밀접한 관련이 있으므로이 작은 차이는 신경 쓰지 않습니다.

컬렉션에 명시 적으로 저장하지 않은 값을 열거 할 수도 있습니다. 예를 들어, 자연수, 소수 등을 열거 할 수 있지만 열거 중에 이러한 값을 계산하고 물리적 컬렉션에서 검색하지 않습니다. 이 경우는 일부 논리에 의해 정의 된 값으로 가상 컬렉션을 열거하는 것으로 이해합니다.


나는 Reed Copsey가 요점을 가지고 있다고 생각합니다. C #에는 무언가를 열거하는 두 가지 주요 방법이 있습니다.

  1. 구현 Enumerable구현 클래스IEnumerator
  2. yield문으로 반복기 구현

첫 번째 방법은 구현하기가 더 어렵고 열거를 위해 개체를 사용합니다. 두 번째 방법은 구현하기가 더 쉽고 연속을 사용합니다.


C # 2+에서 반복기 는 컴파일러가 IEnumerable 및 / 또는 IEnumerable <T> 인터페이스를 자동으로 생성하는 방법입니다.

반복기가 없으면 Current, MoveNext 및 Reset을 포함하여 IEnumerator를 구현하는 클래스를 만들어야합니다 . 이를 위해서는 상당한 작업이 필요합니다. 일반적으로 유형에 대해 IEnumerator <T>를 구현하는 개인 클래스를 만든 다음 yourClass.GetEnumerator ()가 해당 개인 클래스를 생성하고 반환합니다.

반복자는 컴파일러가 간단한 구문 (yield)을 사용하여이를 자동으로 생성하는 방법입니다. 이렇게하면 두 번째 클래스 (IEnumerator)를 지정하지 않고도 클래스에서 직접 GetEnumerator ()를 구현할 수 있습니다. 모든 구성원과 함께 해당 클래스의 구성이 수행됩니다.

Iterator는 개발자에게 매우 친숙합니다. 작업은 훨씬 적은 노력으로 매우 효율적인 방식으로 수행됩니다.

foreach를 사용하면 두 가지가 동일하게 작동합니다 (사용자 지정 IEnumerator를 올바르게 작성하는 경우). 반복자는 삶을 훨씬 더 단순하게 만듭니다.


C #에서 반복기를 호출하는 것은 일반적으로 (C # 세계 외부에서) 생성기 또는 생성기 함수 (예 : Python)라고합니다. 제너레이터 함수는 코 루틴 의 특수한 경우입니다 . AC # 반복기 (생성기)는 특별한 형식의 열거 자 ( IEnumerable인터페이스를 구현하는 데이터 형식 )입니다.

나는 C # 생성기에서 반복기라는 용어를 사용하는 것이 싫다. 왜냐하면 그것은 반복자만큼이나 열거 자이기 때문이다. 마이크로 소프트가 마음을 바꾸기에는 너무 늦었다.

대조적으로 C ++에서 반복자는 주로 컬렉션의 순차 요소에 액세스하는 데 사용되는 값입니다. 값을 검색하기 위해 고급화하고 추론 할 수 있으며 컬렉션 끝에 도달했는지 여부를 테스트 할 수 있습니다.


반복자를 이해하려면 먼저 열거자를 이해해야합니다.

열거자는 순서가 지정된 항목 목록을 한 번에 하나씩 이동할 수있는 수단을 제공하는 전문 개체입니다 (같은 종류의 것을 '커서'라고도 함). .NET 프레임 워크는 열거 자와 관련된 두 가지 중요한 인터페이스 인 IEnumerator와 IEnumerable을 제공합니다. IEnumerator를 구현하는 객체는 그 자체가 열거 자입니다. 다음 회원을 지원합니다.

  • 목록상의 위치를 ​​가리키는 Current 속성

  • 목록을 따라 현재 항목을 하나 이동하는 MoveNext 메소드

  • Reset 메소드는 Current 항목을 초기 위치 (첫 번째 항목 앞)로 이동합니다.

반면에 반복자는 열거 자 패턴을 구현합니다. .NET 2.0은 컴파일러-매니페스트 된 열거자인 반복자를 도입했습니다. 열거 가능한 개체가 직접 또는 간접적으로 GetEnumerаtor를 호출 할 때 컴파일러는 적절한 반복자 개체를 생성하고 반환합니다. 선택적으로, 반복자는 열거 형과 열거 자 객체를 결합 할 수 있습니다.

반복자 블록의 필수 구성 요소는 수율 기준입니다. 반복자와 열거 자 사이에는 한 가지 큰 차이점이 있습니다. 반복자는 Reset 메서드를 구현하지 않습니다. 반복자에서 Reset 메서드를 호출하면 예외가 발생합니다.

반복자의 요점은 열거자를 쉽게 구현할 수 있도록하는 것입니다. 메서드가 정렬 된 항목 목록에 대해 열거 자 또는 열거 가능한 클래스를 반환해야하는 경우 'yield'문을 사용하여 올바른 순서로 각 항목을 반환하도록 작성됩니다.


"foreach 문은 열거 자의 소비자 인 반면 반복자는 열거 자의 생산자입니다."

위의 내용은 "C # 5.0 In A NutShell"에서 설명하는 방법이며 저에게 도움이되었습니다.

즉, foreach 문은 MoveNext () 및 IEnumerator의 Current 속성을 사용하여 시퀀스를 반복하는 반면 반복자는 foreach 문에서 사용할 IEnumerator의 구현을 생성하는 데 사용됩니다. C #에서 yield 문을 포함하는 반복기 메서드를 작성하면 컴파일러가 전용 열거자를 생성합니다. 그리고 시퀀스의 항목을 반복 할 때 개인 열거 자의 MoveNext () 및 Current 속성을 호출합니다. 이러한 메서드 / 속성은 산출 할 값이 남아 있지 않을 때까지 값을 산출하기 위해 반복적으로 호출되는 반복기 메서드의 코드에 의해 구현됩니다.

이것은 C #이 열거 자 및 반복자를 정의하는 방법에 대한 나의 이해입니다.


예제가 제공되지 않았으므로 여기에 도움이 된 것이 있습니다.

열거자는 IEnumerator 인터페이스를 구현하는 클래스 또는 형식에서 .GetEnumerator ()를 호출 할 때 가져 오는 개체입니다. 이 인터페이스가 구현되면 컴파일러가 foreach컬렉션을 "반복"하는 데 사용할 수 있도록 필요한 모든 코드를 만든 것입니다.

'반복'이라는 단어를 반복자와 혼동하지 마십시오. 열거 자와 반복자는 모두 "반복"을 허용합니다. 열거와 반복은 기본적으로 동일한 프로세스이지만 다르게 구현됩니다. 열거는 IEnumerator 인터페이스를 구현했음을 의미합니다. 반복은 클래스에서 반복자 구성을 생성했으며 (아래에 설명 됨) foreach클래스를 호출 하는 것을 의미합니다. 그러면 컴파일러가 자동으로 열거 자 기능을 생성합니다.

또한 열거 자로 스쿼트를 할 필요가 없습니다. MyClass.GetEnumerator()하루 종일 전화를 걸고 아무것도 할 수 없습니다 (예 :

IEnumerator myEnumeratorThatIWillDoNothingWith = MyClass.GetEnumerator()).

클래스의 반복자 구성은 실제로 사용하는 경우에만 실제로 사용됩니다. 즉, foreach클래스에서 호출 했습니다.

다음은 msdn 의 반복기 예제입니다 .

public class DaysOfTheWeek : System.Collections.IEnumerable
{

     string[] days = { "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" };

     //This is the iterator!!!
     public System.Collections.IEnumerator GetEnumerator()
     {
         for (int i = 0; i < days.Length; i++)
         {
             yield return days[i];
         }
     }

}

class TestDaysOfTheWeek
{
    static void Main()
    {
        // Create an instance of the collection class
        DaysOfTheWeek week = new DaysOfTheWeek();

        // Iterate with foreach - this is using the iterator!!! When the compiler
        //detects your iterator, it will automatically generate the Current, 
        //MoveNext and Dispose methods of the IEnumerator or IEnumerator<T> interface
        foreach (string day in week)
        {
            System.Console.Write(day + " ");
        }
    }
}
// Output: Sun Mon Tue Wed Thr Fri Sat

"Iterators are a new feature in C# 2.0. An iterator is a method, get accessor or operator that enables you to support foreach iteration in a class or struct without having to implement the entire IEnumerable interface. Instead, you provide just an iterator, which simply traverses the data structures in your class. When the compiler detects your iterator, it will automatically generate the Current, MoveNext and Dispose methods of the IEnumerable or IEnumerable interface." - msdn


Enumeration deals with objects while iteration deals with values only. Enumeration is used when we use vector hashtable etc while iteration are used in while loop for loop etc. I've never use the yield keyword so I couldn't tell you.

참고URL : https://stackoverflow.com/questions/716238/distinction-between-iterator-and-enumerator

반응형