2010-08-11 7 views
4

저는 C# 2010 Accelerated를 읽고 있습니다. 내가 GetEnumerator를 호출 할 때 yieldIEnumerable에서 C# yield를 이해하는 데 도움이 필요합니다.

, 실제로 시점이 에서 실행되지 않습니다 수율 문이 포함 된 방법의 코드 무엇을 얻을니까. 대신 컴파일러 열거 클래스를 생성하고, 그 클래스가 나도 Some help understanding “yield”

수율로부터 판독 수율 블록 부호

public IEnumerator<T> GetEnumerator() { 
    foreach(T item in items) { 
     yield return item; 
    } 
} 

포함 만 데이터 지연 프로듀서 첫 번째 이 검색된 후 다른 항목을 생성하는 반면, 을 반환하면 목록이 모두 하나로 반환됩니다. go.

이렇게하면 GetEnumerator을 호출 할 때마다 컬렉션에서 1 개 항목을 가져옵니다. 그래서 1 차 전화는 1 차 아이템을 얻습니다. 둘째는 2 등입니다 ...?

+2

를 구경 해주세요. 나의 이해에서 당신은 그것이 정확하다고 설명하는 것처럼 보입니다. 수율은 기본적으로 다음에 다른 객체를 호출 할 때까지 해당 메소드 내에서 실행을 일시 중지합니다. –

답변

6

그것을 생각하는 가장 좋은 방법입니다 foreach에서 사용할 수 있습니다. 그런 다음 다음 항목을 요청하면 왼쪽에있는 코드를 다시 시작하고 yield break 또는 메서드가 끝날 때까지 사이클을 반복합니다.

public IEnumerator<string> enumerateSomeStrings() 
{ 
    yield return "one"; 
    yield return "two"; 
    var array = new[] { "three", "four" } 
    foreach (var item in array) 
     yield return item; 
    yield return "five"; 
} 
1

예 당신이 그것을 이해처럼

public class List 
{ 
    //using System.Collections; 
    public static IEnumerable Power(int number, int exponent) 
    { 
     int counter = 0; 
     int result = 1; 
     while (counter++ < exponent) 
     { 
      result = result * number; 
      yield return result; 
     } 
    } 

    static void Main() 
    { 
     // Display powers of 2 up to the exponent 8: 
     foreach (int i in Power(2, 8)) 
     { 
      Console.Write("{0} ", i); 
     } 
    } 
} 
/* 
Output: 
2 4 8 16 32 64 128 256 
*/ 
0

것 같습니다 사용하는 방법을 보여줍니다 MSDN에서 오른쪽을 heres 예를 이잖아. 당신은 루프 수에 2 등에서 두 번째 전화를 1에서 첫 번째 항목을 반환하여

foreach (MyObject myObject in myObjectCollection) 
{ 
    // Do something with myObject 
} 

: 당신이 그렇게 설명으로

yield

는이 같은 코드를 작성할 수있는 클래스의 GetEnumerator에 사용됩니다 컬렉션의 모든 요소에 적용됩니다.

yieldMyObjectCollection으로 정의됩니다. 당신이 첫 번째 요청 (A foreach 예를 들면)를 IEnumerator에서 항목, 그것은 트로프에게 방법을 실행을 시작하고,이 yield return 안타 때 실행을 일시 정지하고 당신을 위해 항목을 반환 할 때

1

귀하의 질문을 이해하면 귀하의 이해가 올바르지 않습니다. 나는 affraid입니다. yield 문 (yield return 및 yield break)은 매우 영리한 컴파일러 트릭입니다. 코드는 실제로 IEnumerable을 구현하는 클래스로 컴파일됩니다. 이 클래스의 인스턴스가 메서드에서 반환 할 것입니다. ins.GetEnumerator()를 호출 할 때 인스턴스에 'ins'을 호출하면 시퀀스에 더 이상 요소가없는 경우 MoveNext()에 대한 각 호출에 대해 콜렉션에서 다음 요소를 생성 한 (yield 부분이이 부분을 담당 함) IEnumerator를 얻습니다. (예 : yield break가 발생 함) MoveNext()는 false를 반환하고 이후의 호출은 예외를 발생시킵니다.따라서 (다음) 요소를 생성 한 GetEnumerator가 아닌 MoveNext 호출

2

IEnumerator<T> 인터페이스를 살펴보십시오. 무슨 일이 일어나고 있는지 분명히 밝힐 수 있습니다. 컴파일러는 코드를 가져와 IEnumerable<T>IEnumerator<T>을 구현하는 클래스로 바꿉니다. GetEnumerator() 호출은 단순히 클래스 자체를 반환합니다.

구현은 기본적으로 MoveNext()를 호출 할 때마다 yield return까지 코드를 실행 한 다음 현재 값을 반환 값으로 설정하는 상태 시스템입니다. foreach 루프는이 열거자를 사용하여 열거 된 항목을 거쳐 루프의 각 반복 전에 MoveNext()를 호출합니다. 컴파일러는 여기에서 매우 멋진 것들을 수행하고 있습니다. yield return은 언어에서 가장 강력한 구조 중 하나입니다. 프로그래머의 관점에서, 요청이있을 때 지연적으로 항목을 반환하는 것은 쉬운 방법 일뿐입니다.

0

yield 키워드를 이해하는 간단한 방법은 수익률 반환 키워드를 사용하여 반환 할 때 반복 결과를 보관하는 데 별도의 클래스가 필요하지 않습니다. 일반적으로 컬렉션을 반복 할 때 결과를 반환하려면 컬렉션 객체 을 사용하여 결과를 저장합니다. 예를 봅시다.

공공 정적 목록 곱셈 (INT 번호, INT 회)

{ 
     List<int> resultList = new List<int>(); 
     int result = number; 
     for(int i=1;i<=times;i++) 
     { 
      result=number*i; 
      resultList.Add(result); 
     } 
     return resultList; 
    } 

정적 무효 메인 (문자열 []에 args) 위의 예에서

{ 
     foreach(int i in Multiplication(2,10)) 
     { 
      Console.WriteLine(i); 
     } 
     Console.ReadKey(); 
    } 

, 나는 결과를 반환 할 2 곱하기 10 번. 그래서 나는 곱셈을 만듭니다 2의 곱셈을 10 번 반환하고 목록에 결과를 저장하고 주된 메서드가 곱셈 메서드를 호출하면 컨트롤이 루프를 10 번 반복하고 결과를 목록에 저장합니다 . 이것은 yield returns를 사용하는 없이입니다. 내가 그것을

같은

공공 정적는 IEnumerable 곱셈 (INT 번호, int로 번) 보이는이 사용 항복 반환

  { 
     int result = number; 
     for(int i=1;i<=times;i++) 
     { 
      result=number*i; 
      yield return result; 
     } 
    } 

정적 무효 메인 (문자열 []에 args)

{ 
     foreach(int i in Multiplication(2,10)) 
     { 
      Console.WriteLine(i); 
     } 
     Console.ReadKey(); 
    } 
을 수행하려는 경우 가정

이제 곱하기 메서드에 약간의 변경이 있습니다. 반환 유형은 IEnumerable이며 결과를 보유 할 다른 목록은 없습니다. 반환 값 형식은 IEnumerable 또는 IEnumerator 여야하고 Yield는 상태 저장 반복을 제공하므로 결과를 저장하기 위해 여분의 클래스가 필요하지 않습니다. 따라서 위의 예제에서 Multiplication 메서드가 Main 메서드에서 호출되면 첫 번째 반복에서 결과를 계산하고 결과를 main 메서드로 반환하고 루프로 돌아와 두 번째 반복 결과를 계산 한 다음 결과를 이 방법으로 Yield는 각 반복마다 메서드를 하나씩 호출하는 결과를 반환합니다. 반복을 일으키는 Yield와 함께 사용되는 다른 Keyword Break가 중지됩니다. 위의 예에서, 예를 들어 난 방법은 다음과 같다 다음 시간의 절반 번호 (2분의 10 = 5)을위한 승산을 계산하려면 다음

공용 static IEnumerable을 곱셈 (INT 번호 int로 회)

{ 
     int result = number; 
     for(int i=1;i<=times;i++) 
     { 
      result=number*i; 
      yield return result; 
      if (i == times/2) 
       yield break; 
     } 

    } 

이 방법은 이제 2, 5 배의 곱셈이됩니다. 이것이 유익의 개념을 이해하는 데 도움이되기를 바랍니다. 더 많은 것을 위해 정보는 http://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx

관련 문제