2010-03-23 2 views
17

다음 코드를 단계별로 수행하면 ReturnOne() 호출을 건너 뜁니다.중첩 된 메서드에서 C# yield

static IEnumerable<int> OneThroughFive() 
{ 
    ReturnOne(); 
    yield return 2; 
    yield return 3; 
    yield return 4; 
    yield return 5; 
} 

static IEnumerator<int> ReturnOne() 
{ 
    yield return 1; 
} 

내가하고있는 일이 유효하지 않기 때문에 컴파일러가이를 제거한다고 가정 할 수 있습니다. 열거 형을 여러 가지 방법으로 분리 할 수있는 기능이 필요합니다. 이것이 가능한가?

답변

30

실제로는 ReturnOne의 결과가 사용되지 않습니다. 메소드를 호출하고 반환 값을 무시하면 ... 실제로 코드가 실행되는 것을 본 적이 없다는 것을 의미합니다. 당신은 다음과 같이 그것을 할 수 :

static IEnumerable<int> OneThroughFive() 
{ 
    foreach (int x in ReturnOne()) 
    { 
     yield x; 
    } 
    yield return 2; 
    yield return 3; 
    yield return 4; 
    yield return 5; 
} 

C#을 (현재 적어도 : "모든 수율"구성의 일종이 없습니다.

당신이 한걸음 나아갈 수 없다는 사실은 당신이 반복자 블록 내에서 호출을한다는 사실과 아무런 상관이 없습니다. 당신이 을 시작할 때까지 반복기 블록의 결과를 , 어떤 코드도 실행되지 않습니다. 그렇기 때문에 인수 검증과 항복 검증을 분리해야합니다. 에서 무료 장으로 일어나는 - 깊이에서 C 번호의 6 장을 읽어 자세한 내용

public IEnumerator<string> ReturnSubstrings(string x) 
{ 
    if (x == null) 
    { 
     throw ArgumentNullException(); 
    } 
    return ReturnSubstringsImpl(x); 
} 

private IEnumerator<string> ReturnSubstringsImpl(string x) 
{ 
    for (int i = 0; i < x.Length; i++) 
    { 
     yield return x.Substring(i); 
    } 
} 

:이처럼 쓸 필요가

public IEnumerator<string> ReturnSubstrings(string x) 
{ 
    if (x == null) 
    { 
     throw ArgumentNullException(); 
    } 
    for (int i = 0; i < x.Length; i++) 
    { 
     yield return x.Substring(i); 
    } 
} 
... 
ReturnSubstring(null); // No exception thrown 

예를 들어,이 코드를 고려 초판 :) Grab it here.

+0

다소 편리 할 수 ​​있습니다. – Luiscencio

+0

@ 존 : 실제로 첫 번째'ReturnSubstrings'의 결과를 사용하려고하면 어떻게 될까요? 'NullPointerException' 또는'ArgumentNullException'을 얻을 수 있습니까? –

+0

나는이 스레드를 읽을 때, 내가 아래로 스크롤하여 저자를보기 전에 jon skeet이이 답안을 작성했다는 것을 알았습니다. @ 존, 당신은 정말로 더 나가야합니다. 하지만 지금은 새로운 것을 가르쳐 주신데 대해 다시 한번 감사드립니다. – fearofawhackplanet