¿Para qué se utiliza la palabra clave de rendimiento en C#?

Resuelto Herms asked hace 16 años • 20 respuestas

En la pregunta ¿Cómo puedo exponer solo un fragmento de IList<>?, una de las respuestas tenía el siguiente fragmento de código:

IEnumerable<object> FilteredList()
{
    foreach(object item in FullList)
    {
        if(IsItemInPartialList(item))
            yield return item;
    }
}

¿Qué hace la palabra clave de rendimiento allí? He visto referencias a él en un par de lugares y en otra pregunta, pero no he descubierto muy bien qué hace realmente. Estoy acostumbrado a pensar en el rendimiento en el sentido de que un hilo cede ante otro, pero eso no parece relevante aquí.

Herms avatar Sep 02 '08 20:09 Herms
Aceptado

La yieldpalabra clave contextual realmente hace mucho aquí.

La función devuelve un objeto que implementa la IEnumerable<object>interfaz. Si una función que llama comienza foreacha funcionar sobre este objeto, la función se llama nuevamente hasta que "cede". Este es el azúcar sintáctico introducido en C# 2.0 . En versiones anteriores tenías que crear tus propios IEnumerableobjetos IEnumeratorpara hacer cosas como esta.

La forma más sencilla de entender un código como este es escribir un ejemplo, establecer algunos puntos de interrupción y ver qué sucede. Intente seguir este ejemplo:

public void Consumer()
{
    foreach(int i in Integers())
    {
        Console.WriteLine(i.ToString());
    }
}

public IEnumerable<int> Integers()
{
    yield return 1;
    yield return 2;
    yield return 4;
    yield return 8;
    yield return 16;
    yield return 16777216;
}

Cuando siga el ejemplo, encontrará la primera llamada a Integers()return 1. La segunda llamada regresa 2y la línea yield return 1no se vuelve a ejecutar.

Aquí hay un ejemplo de la vida real:

public IEnumerable<T> Read<T>(string sql, Func<IDataReader, T> make, params object[] parms)
{
    using (var connection = CreateConnection())
    {
        using (var command = CreateCommand(CommandType.Text, sql, connection, parms))
        {
            command.CommandTimeout = dataBaseSettings.ReadCommandTimeout;
            using (var reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    yield return make(reader);
                }
            }
        }
    }
}
Mendelt avatar Sep 02 '2008 13:09 Mendelt

Iteración. Crea una máquina de estado "bajo las sábanas" que recuerda dónde estaba en cada ciclo adicional de la función y continúa desde allí.

Joel Coehoorn avatar Sep 02 '2008 13:09 Joel Coehoorn

El rendimiento tiene dos grandes usos,

  1. Ayuda a proporcionar iteraciones personalizadas sin crear colecciones temporales.

  2. Ayuda a realizar iteraciones con estado. ingrese la descripción de la imagen aquí

Para explicar los dos puntos anteriores de manera más demostrativa, he creado un video simple que puedes verlo aquí.

Shivprasad Koirala avatar Apr 12 '2013 17:04 Shivprasad Koirala