significa salir que para for comando codigo array c# .net

c# - salir - una preocupación por el rendimiento y la ruptura de un foreach



que significa for en c# (3)

A ver si me sale tu pregunta.

foreach(Person p in getPeople()) { // break here }

debido a la palabra clave foreach, el enumerador se elimina correctamente. Durante la eliminación de Enumerator, la ejecución de getPeople () se termina. Así que la conexión se limpia correctamente.

¿Hay una forma adecuada de romper con un foreach tal que IEnumerable <> sepa que he terminado y que debería limpiarse?

Considere el siguiente código:

private static IEnumerable<Person> getPeople() { using (SqlConnection sqlConnection = new SqlConnection("...")) { try { sqlConnection.Open(); using (SqlCommand sqlCommand = new SqlCommand("select id, firstName, lastName from people", sqlConnection)) { using (SqlDataReader reader = sqlCommand.ExecuteReader()) { while (reader.Read()) yield return new Person(reader.GetGuid(0), reader.GetString(1), reader.GetString(2)); } } } finally { Console.WriteLine("finally disposing of the connection"); if (sqlConnection.State == System.Data.ConnectionState.Open) sqlConnection.Close(); } } }

Si el consumidor no rompe con el foreach, entonces todo está bien y el lector devolverá el valor falso, el bucle while finalizará y la función limpia el comando y la conexión de la base de datos. Pero, ¿qué sucede si la persona que llama rompe el foreach antes de que termine?


Excelente pregunta. No tienes que preocuparte por esto; El compilador lo cuida por ti. Básicamente, lo que hacemos es colocar el código de limpieza para los bloques finalmente en un método de limpieza especial en el iterador generado. Cuando el control abandona el bloque foreach del llamador, el compilador genera un código que llama al código de limpieza en el iterador.

Un ejemplo simplificado:

static IEnumerable<int> GetInts() { try { yield return 1; yield return 2;} finally { Cleanup(); } }

Su pregunta es básicamente "¿Se llama a Cleanup () en este escenario?"

foreach(int i in GetInts()) { break; }

Sí. El bloque iterador se genera como una clase con un método de Disposición que llama a Limpieza, y luego el bucle foreach se genera como algo similar a:

{ IEnumerator<int> enumtor = GetInts().GetEnumerator(); try { while(enumtor.MoveNext()) { i = enumtor.Current; break; } } finally { enumtor.Dispose(); } }

Así que cuando ocurre la ruptura, finalmente se hace cargo y se llama al eliminador.

Vea mi serie reciente de artículos si desea obtener más información sobre algunos de los casos extraños de esquinas que consideramos en el diseño de esta función.

http://blogs.msdn.com/ericlippert/archive/tags/Iterators/default.aspx


Puedes usar el enunciado

yield break;

para salir de un ciclo de rendimiento temprano, pero su código revela un malentendido, creo ... Cuando usa la declaración "utilizando",

using (SqlConnection sqlConnection = new SqlConnection("...")) { // other stuff }

AUTOMÁTICAMENTE obtienes un bloque de try try en el código IL compilado, y el bloque final llamará a Dispose, y en el código de Dispose la conexión se cerrará ...