2010-05-03 4 views

답변

13

수율 구현이 필요할 때까지 코드에 도달하지 않습니다. 예를 들어

,이 코드 :

public IEnumerable<int> GetInts() 
{ 
    yield return 1; 
    yield return 2; 
    yield return 3; 
} 

실제로 IEnumerable<int>를 구현하고 GetInts()의 몸이 그 클래스의 인스턴스를 반환하는 중첩 된 클래스로 컴파일됩니다.

당신이 볼 수있는 반사판을 사용하여 :

public IEnumerable<int> GetInts() 
{ 
    <GetInts>d__6d d__d = new <GetInts>d__6d(-2); 
    d__d.<>4__this = this; 
    return d__d; 
} 

편집 - 더 정보에 대한 GetInts 구현을 추가 :
이 구현은 EnumeratorMoveNext() 방법을 기반으로이 게으른 만드는 방법. 열거 형 중첩 클래스가 생성되면 (예제에서는 <GetInts>d__6d) 상태가 있고 각 상태에 값이 연결됩니다 (이 경우는 단순한 경우입니다. 고급 사례에서는 코드가 상태에 도달하면 값이 평가됩니다). 우리가 <GetInts>d__6dMoveNext() 코드를 살펴 경우 우리가 상태를 볼 수 있습니다 : 열거가 현재 개체에 대한 요구는 현재 상태로 연결되어있는 객체를 반환

private bool MoveNext() 
{ 
    switch (this.<>1__state) 
    { 
     case 0: 
      this.<>1__state = -1; 
      this.<>2__current = 1; 
      this.<>1__state = 1; 
      return true; 

     case 1: 
      this.<>1__state = -1; 
      this.<>2__current = 2; 
      this.<>1__state = 2; 
      return true; 

     case 2: 
      this.<>1__state = -1; 
      this.<>2__current = 3; 
      this.<>1__state = 3; 
      return true; 

     case 3: 
      this.<>1__state = -1; 
      break; 
    } 
    return false; 
} 

.

코드가이 예제에서 볼 수 필요한 때만 평가되고 있음을 보여주기 위해 :

[TestFixture] 
public class YieldExample 
{ 
    private int flag = 0; 
    public IEnumerable<int> GetInts() 
    { 
     yield return 1; 
     flag = 1; 
     yield return 2; 
     flag = 2; 
     yield return 3; 
     flag = 3; 
    } 

    [Test] 
    public void Test() 
    { 
     int expectedFlag = 0; 
     foreach (var i in GetInts()) 
     { 
      Assert.That(flag, Is.EqualTo(expectedFlag)); 
      expectedFlag++; 
     } 

     Assert.That(flag, Is.EqualTo(expectedFlag)); 
    } 
} 

나는 그것이 좀 더 분명 희망을. Reflector를 사용하여 코드를 살펴보고 "yield"코드를 변경할 때 컴파일 된 코드를 관찰하는 것이 좋습니다.

+0

@Elisha : GetInts()에 대한 자세한 정보를 제공하십시오. –

+0

@masoud ramezani는 GetInts 중첩 열거 자 클래스에 대한 추가 정보를 추가했습니다. – Elisha

+0

완전한 대답을 가져 주셔서 감사합니다. –

7

컴파일러가 yield return를 사용할 때 무엇을하고 있는지에 대해 더 알고 싶다면, 존 소총으로이 문서 확인 : Iterator block implementation details 기본적으로 yield 문을 사용하여 위해 구현 반복자

+1

Briljant가 실제로 리디렉션합니다. +1 – peSHIr

4

state machine 구현하는 클래스로 컴파일됩니다.

foreach (= 반복하고 실제로 사용함) 반환 된 IEnumerable<T> 코드가 실제로 실행되지 않습니다. 그리고 당신이한다면, 반환 할 다음 값을 결정하는 데 필요한 최소한의 코드 만 실행되고 다음 값이 요청 될 때 실행을 다시 시작합니다.

디버거에서 이러한 코드를 한 단계 수행하면 실제로이 문제가 발생할 수 있습니다. 적어도 한 번 시도해보십시오. 나는이 일이 단계적으로 일어나는 것을 보는 것이 밝다고 생각합니다.

관련 문제