2010-03-23 28 views
17

Si paso por el siguiente código, la llamada a ReturnOne() se omite.Rendimiento de C# en el método anidado

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

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

Solo puedo suponer que el compilador lo está eliminando porque lo que estoy haciendo no es válido. Me gustaría la posibilidad de aislar mi enumeración en varios métodos. es posible?

Respuesta

30

No está usando realmente el resultado de ReturnOne. Estás llamando al método e ignorando el valor de retorno ... lo que significa que nunca verías ejecutar tu código. Usted puede hacerlo de esta manera:

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

C# no (en la actualidad al menos :) tiene una especie de "rendimiento de todo" construir.

El hecho de que usted no está consiguiendo a entrar en él no tiene nada que ver con el hecho de que tienes una llamada dentro de un bloque de iterador - es sólo que hasta que empiece a usar el resultado de un bloque de iterador , no se ejecuta el código. Es por eso que necesita separar la validación de argumento de ceder. Por ejemplo, considere este código:

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 

Usted tiene que escribir así:

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

Para más detalles, lea el capítulo 6 de C# en profundidad - que pasa a ser un capítulo libre en el primera edición :) Grab it here.

+0

que podría ser de alguna manera útil ... – Luiscencio

+0

@Jon: ¿Qué pasará si intentas utilizar realmente los resultados del primer 'ReturnSubstrings'? ¿Obtendrá una 'NullPointerException', o una' ArgumentNullException'? –

+0

Me encanta cómo, al leer este hilo, sabía que jon skeet escribió esta forma de respuesta antes de que me hubiera desplazado al final y visto al autor. @jon, deberías salir más. pero por ahora, gracias de nuevo por enseñarme algo nuevo. – fearofawhackplanet