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
yield
se puede usar en general.Respuestas:
Eficiencia
La
yield
palabra clave crea efectivamente una enumeración perezosa sobre los elementos de la colección que puede ser mucho más eficiente. Por ejemplo, si suforeach
ciclo itera solo sobre los primeros 5 elementos de 1 millón de elementos, eso es todo lo queyield
devuelve, y no acumuló una colección de 1 millón de elementos internamente primero. Del mismo modo que se quiere utilizaryield
conIEnumerable<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
yield
vuelve 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
yield
palabra 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 laforeach
palabra 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
yield
palabra clave:Y así es como lo uso:
No tengo que hacer un
for
ciclo 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
yield
operador 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
command
clase 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
SqlCommand
propiedades y parámetros todo el tiempo.Entonces, hay una función que se ve así:
La clase que hereda esta
command
clase tiene las propiedadesAge
yName
.Luego puede renovar un
command
objeto lleno de sus propiedades y pasarlo a unadb
interfaz 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
MarkChecksum
mé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 return
para 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