2011-11-25 9 views
9

La documentación yield palabra clave dice:¿La palabra clave de rendimiento es útil fuera de un bloque de iterador?

El rendimiento señales de palabras clave para el compilador que el método en el que aparece es un bloque de iterador.

He encontrado el código utilizando la palabra clave yield fuera de cualquier bloque de iterador. ¿Debería considerarse esto como un error de programación o está bien?

EDITAR Lo sentimos olvidó de publicar mi código:

int yield = previousVal/actualVal; 
return yield; // Should this be allowed!!!??? 

Gracias.

+7

** Sí **, es muy útil. – dlev

+4

Quien haya ideado la línea "devolver rendimiento"; es un genio malvado de proporciones épicas. –

+0

¡Tenemos un buen hombre de código base! Hice esta pregunta porque estaba argumentando en contra de este tipo de codificación ... Quería escuchar lo que piensa la comunidad al respecto – GETah

Respuesta

22

Es bien es utilizar yield fuera de un bloque iterador - sólo significa que no está siendo utilizado como una palabra clave contextual .

Por ejemplo:

// No idea whether this is financially correct, but imagine it is :) 
decimal yield = amountReturned/amountInvested; 

En ese momento no es una palabra clave contextual (Es Nunca una palabra clave "lleno"), es sólo un identificador. A menos que sea claramente la mejor opción en términos de claridad normal, trataría de evitar usarlo de todos modos, pero a veces podría ser.

Sólo se puede utilizar como palabra clave contextual de yield return y yield break, que sólo son válidas siempre en un bloque de iterador. (Son lo que convierte un método en un iterador.)

EDITAR: Para responder a su pregunta "should this be allowed" ... sí, debería. De lo contrario, todo el código C# 1 existente que usó yield como identificador se habría vuelto inválido cuando se haya liberado C# 2. Se debe usar con cuidado, y el equipo C# se ha asegurado de que nunca sea realmente ambiguo, pero tiene sentido que sea válido.

Lo mismo ocurre con muchas otras palabras clave contextuales: "desde", "seleccionar", "dónde", etc. ¿Desea evitar que sean identificadores alguna vez?

+0

Sí, este es exactamente mi punto – GETah

+1

@GETah: Bueno, en realidad no es una * palabra clave * en el contexto que usted ha dado ... –

+0

Jon, estoy probando mi comprensión aquí ... Es el 'rendimiento' como se usa en el método como mi 'GetNotVeryRandomNumbers' en [mi respuesta] (http://stackoverflow.com/q/8273864/593627) no en un bloque iterador? (Pensé que 'yield' crea uno, pero no tiene que existir dentro de uno). Esto parece contradecir su última declaración. –

5

yield es una palabra clave contextual .
Cuando se usa en yield return o yield break, es una palabra clave y crea un iterador.
Cuando se usa en otro lugar, es un identificador normal.

yield puede ser extremadamente útil para more than ordinary collections; también se puede usar para implementar corutinas primitivas.

+0

+1 para el enlace a su pregunta interesante anterior – phoog

11

Lo que está diciendo es que si usa yield en un método, el método se convierte en un bloque iterador.

Además, como yield es contextual keyword, se puede utilizar libremente en cualquier otro lugar, donde las palabras clave completas no pueden (por ejemplo, nombres de variables).

void AnotherMethod() 
{ 
    foreach(var NotRandomNumber in GetNotVeryRandomNumbers()) 
    { 
     Console.WriteLine("This is not random! {0}", NotRandomNumber); 
    } 
} 

IEnumerable<int> GetNotVeryRandomNumbers() 
{ 
    yield return 1; 
    yield return 53; 
    yield return 79; 
    yield return 1; 
    yield return 789; 
} 

// Perhaps more useful function below: (untested but you get the idea) 
IEnumerable<Node> DepthFirstIteration(Node) 
{ 
    foreach(var Child in Node.Children) 
    { 
     foreach(var FurtherChildren in DepthFirstIteration(Child)) 
     { 
      yield return FurtherChildren; 
     } 
    } 
    yield return Node; 
} 

Consulte también: Esta respuesta, que muestra el uso de un producto después de otro. Clever Uses of Iterator Blocks

+0

Podría estar equivocado, pero creo que esto no tiene sentido. La pregunta no es "¿son útiles los bloques del iterador?" - sino más bien: cuando se usa *** fuera de *** un bloque iterador, ¿es útil el "rendimiento"? –

+0

En el método 'GetNotVeryRandomNumbers' no está en un bloque iterador (lo crea), ¿o estoy malinterpretando bloques iteradores? –

+0

Con la edición, está claro que definitivamente me perdí el objetivo de la pregunta. (Vaya) –

Cuestiones relacionadas