Después de casi 4 años de experiencia, no he visto un código donde se use la palabra clave de rendimiento . ¿Alguien puede mostrarme un uso práctico (junto con la explicación) de esta palabra clave, y si es así, ¿no hay otras formas más fáciles de completar lo que puede hacer?
76

yieldse puede usar en general.Respuestas:
Eficiencia
La
yieldpalabra clave crea efectivamente una enumeración perezosa sobre los elementos de la colección que puede ser mucho más eficiente. Por ejemplo, si suforeachciclo itera solo sobre los primeros 5 elementos de 1 millón de elementos, eso es todo lo queyielddevuelve, y no acumuló una colección de 1 millón de elementos internamente primero. Del mismo modo que se quiere utilizaryieldconIEnumerable<T>valores de retorno en sus propios escenarios de programación para lograr la misma eficiencia.Ejemplo de eficiencia obtenida en un escenario determinado
No es un método iterador, uso potencial ineficiente de una gran colección
(la colección intermedia se construye con muchos elementos)
Versión de iterador, eficiente
(no se crea una colección intermedia)
Simplifica algunos escenarios de programación
En otro caso, hace que algunos tipos de clasificación y fusión de listas sean más fáciles de programar porque simplemente
yieldvuelve a colocar los elementos en el orden deseado en lugar de ordenarlos en una colección intermedia e intercambiarlos allí. Hay muchos escenarios de este tipo.Un solo ejemplo es la fusión de dos listas:
Este método devuelve una lista contigua de elementos, efectivamente una fusión sin necesidad de una colección intermedia.
Más información
La
yieldpalabra clave sólo se puede utilizar en el contexto de un método iterador (que tiene un tipo de retorno deIEnumerable,IEnumerator,IEnumerable<T>, oIEnumerator<T>.) Y hay una relación especial conforeach. Los iteradores son métodos especiales. La documentación de rendimiento de MSDN y la documentación del iterador contienen mucha información interesante y explicaciones de los conceptos. Asegúrese de correlacionarlo con laforeachpalabra clave al leerlo también, para complementar su comprensión de los iteradores.Para conocer cómo los iteradores logran su eficiencia, el secreto está en el código IL generado por el compilador de C #. La IL generada para un método iterador difiere drásticamente de la generada para un método regular (no iterador). Este artículo (¿Qué genera realmente la palabra clave Yield?) Proporciona ese tipo de información.
fuente
database.Customers.Count()enumera toda la enumeración de clientes, por lo que se requiere un código más eficiente para revisar cada elemento?Hace algún tiempo tuve un ejemplo práctico, supongamos que tiene una situación como esta:
El objeto del botón no conoce su propia posición en la colección. La misma limitación se aplica para
Dictionary<T>u otros tipos de colecciones.Aquí está mi solución usando la
yieldpalabra clave:Y así es como lo uso:
No tengo que hacer un
forciclo sobre mi colección para encontrar el índice. Mi botón tiene una ID y esto también se usa como índiceIndexerList<T>, por lo que evita cualquier ID o índice redundante , ¡eso es lo que me gusta! El índice / Id puede ser un número arbitrario.fuente
Un ejemplo práctico se puede encontrar aquí:
http://www.ytechie.com/2009/02/using-c-yield-for-readability-and-performance.html
Hay una serie de ventajas de usar el rendimiento sobre el código estándar:
Sin embargo, como dijo Jan_V (solo páseme unos segundos :-) puede vivir sin él porque internamente el compilador producirá un código casi idéntico en ambos casos.
fuente
Aquí hay un ejemplo:
https://bitbucket.org/ant512/workingweek/src/a745d02ba16f/source/WorkingWeek/Week.cs#cl-158
La clase realiza cálculos de fechas basados en una semana laboral. Puedo decirle a una instancia de la clase que Bob trabaja de 9:30 a 17:30 todos los días de la semana con un descanso de una hora para el almuerzo a las 12:30. Con este conocimiento, la función AscendingShifts () generará objetos de turno de trabajo entre las fechas proporcionadas. Para enumerar todos los turnos de trabajo de Bob entre el 1 de enero y el 1 de febrero de este año, lo usaría así:
La clase realmente no itera sobre una colección. Sin embargo, los cambios entre dos fechas pueden considerarse como una colección. El
yieldoperador hace posible iterar sobre esta colección imaginada sin crear la colección misma.fuente
Tengo una pequeña capa de datos db que tiene una
commandclase en la que establece el texto del comando SQL, el tipo de comando y devuelve un IEnumerable de 'parámetros de comando'.Básicamente, la idea es tener comandos CLR escritos en lugar de llenar manualmente
SqlCommandpropiedades y parámetros todo el tiempo.Entonces, hay una función que se ve así:
La clase que hereda esta
commandclase tiene las propiedadesAgeyName.Luego puede renovar un
commandobjeto lleno de sus propiedades y pasarlo a unadbinterfaz que realmente realiza la llamada de comando.En general, es muy fácil trabajar con comandos SQL y mantenerlos escritos.
fuente
Aunque el caso de fusión ya se ha cubierto en la respuesta aceptada, permítame mostrarle el método de extensión de parámetros de fusión de rendimiento ™:
Lo uso para construir paquetes de un protocolo de red:
El
MarkChecksummétodo, por ejemplo, se ve así. Y también tiene unyield:Pero tenga cuidado al usar métodos agregados como Sum () en un método de enumeración, ya que desencadenan un proceso de enumeración separado.
fuente
El repositorio de ejemplos de Elastic Search .NET tiene un excelente ejemplo de cómo usar
yield returnpara dividir una colección en varias colecciones con un tamaño especificado:https://github.com/elastic/elasticsearch-net-example/blob/master/src/NuSearch.Domain/Extensions/PartitionExtension.cs
fuente
Ampliando la respuesta de Jan_V, acabo de llegar a un caso del mundo real relacionado con él:
Necesitaba usar las versiones Kernel32 de FindFirstFile / FindNextFile. Obtiene un identificador de la primera llamada y lo alimenta a todas las llamadas posteriores. Envuelva esto en un enumerador y obtendrá algo que puede usar directamente con foreach.
fuente