2010-03-23 6 views
17

Se passo il seguente codice, la chiamata a ReturnOne() viene saltata.C n. Resa in metodo nidificato

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

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

Posso solo supporre che il compilatore lo stacchi perché ciò che sto facendo non è valido. Mi piacerebbe la possibilità di isolare la mia enumerazione in vari metodi. È possibile?

risposta

30

Attualmente non si sta utilizzando il risultato di ReturnOne. Stai chiamando il metodo e ignorando il valore restituito ... il che significa che non vedresti mai alcun codice in esecuzione. È possibile fare in questo modo:

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

C# non (attualmente almeno :) hanno una sorta di "resa tutti" costruire.

Il fatto che non stai ricevendo fare un passo in esso non ha nulla a che fare con il fatto che hai una chiamata all'interno di un blocco iteratore - è solo che fino a quando si inizia a utilizzando il risultato di un blocco iteratore , nessuno dei codici funziona. Ecco perché è necessario separare la validazione dell'argomento dal cedimento. Ad esempio, si consideri questo codice:

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 

Hai bisogno di scrivere in questo modo:

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

Per ulteriori informazioni, leggere il capitolo 6 di C# in profondità - che risulta essere un capitolo gratuito nella prima edizione :) Grab it here.

+0

che potrebbe essere in qualche modo utile ... – Luiscencio

+0

@Jon: Cosa succederà se proverai a utilizzare effettivamente i risultati del primo 'ReturnSubstrings'? Otterrai un 'NullPointerException', o un' ArgumentNullException'? –

+0

Mi piace come, durante la lettura di questo thread, sapevo che Jon Skeet ha scritto questa risposta prima di scorrere verso il basso e vedere l'autore. @jon, dovresti davvero uscirne di più. ma per ora, grazie ancora per avermi insegnato qualcosa di nuovo. – fearofawhackplanet