este código:Bug en el método File.ReadLines (..) de .NET Framework 4.0
IEnumerable<string> lines = File.ReadLines("file path");
foreach (var line in lines)
{
Console.WriteLine(line);
}
foreach (var line in lines)
{
Console.WriteLine(line);
}
lanza una ObjectDisposedException : {"Cannot read from a closed TextReader."}
si se ejecuta la segunda foreach
. Parece que el objeto iterador devuelto desde File.ReadLines(..)
no se puede enumerar más de una vez. Debe obtener un nuevo objeto iterador llamando al File.ReadLines(..)
y luego usarlo para iterar.
Si sustituyo File.ReadLines(..)
con mi versión (parámetros no se verifican, es sólo un ejemplo):
public static IEnumerable<string> MyReadLines(string path)
{
using (var stream = new TextReader(path))
{
string line;
while ((line = stream.ReadLine()) != null)
{
yield return line;
}
}
}
es posible repetir más de una vez las líneas del archivo.
Una investigación que utiliza .Net Reflector
mostró que la implementación de File.ReadLines(..)
llama a un File.InternalReadLines(TextReader reader)
privado que crea el iterador real. El lector pasó como un parámetro se utiliza en el método MoveNext()
del iterador para obtener las líneas del archivo y se elimina cuando llegamos al final del archivo. Esto significa que una vez que MoveNext()
devuelve falso no hay forma de iterar una segunda vez porque el lector está cerrado y debe obtener un nuevo lector creando un nuevo iterador con el método ReadLines(..)
.En mi versión, se crea un nuevo lector en el MoveNext()
método cada vez que comenzamos una nueva iteración.
¿Es este el comportamiento esperado del método File.ReadLines(..)
?
Me parece preocupante el hecho de que es necesario llamar al método cada vez antes de enumerar los resultados. También debería llamar al método cada vez antes de repetir los resultados de una consulta de Linq que utiliza el método.
_ "¿Es este el comportamiento esperado del método File.ReadLines (..)?" _ Sí. Si ha consumido un 'StreamReader', será eliminado. No hay camino de ida y vuelta. Si lo necesita, debe usar 'File.ReadAllLines'. –
En realidad, una solución simple como 'IEnumerable ReadLinesFixed (ruta de cadena) {foreach (línea var en File.ReadLines (ruta)) produce la línea de retorno; } 'funciona también. –
Vlad