¿Qué hay de malo en este código? (C#)

Buenas 🙂

Al estilo de muchos blogs que visito habitualmente y que proponen pequeños acertijos en base a un código que tiene un error (muchas veces no aparente, otras más evidente), os propongo hoy uno, que me he encontrado revisando código.

Así que, amigos ¿qué hay de malo en este código?

if (!File.Exists(fname))

{

    File.Create(fname);

}

// Hacemos lo que sea…

Sencillo, ¿no? Si el fichero no existe lo creamos y luego hacemos lo que se supone que tengamos que hacer. Parece sencillo, pero hay algo que se nos escapa… ¿Qué puede ser?

Un saludo!

10 comentarios sobre “¿Qué hay de malo en este código? (C#)”

  1. Hola Eduard,

    No se si los tiros van por lo que pasaría si en el momento de hacer la comprobación de si existe, el fichero está pillado por otro proceso, entonces devolvería false e intentaría crearlo…

    Un saludo

  2. Pudiera ser que el usuario que ejecuta el fragmento de código no contara con permisos suficientes para acceder a la ruta, en cuyo caso File.Exists devolvería false e intentaría crearse.

  3. Hola Eduard,

    Lo lógico es que lo hagas justo al revés, es decir si el fichero existe lo eliminas y lo vuelves a crear o por lo menos así pienso lo pienso yo:)

    if (File.Exists(fname))
    {
    File.Delete(fname);
    }
    using (FileStream fs = File.Create(fname))
    {
    //resto de cosas
    }

    Un Saludo

  4. Revisando un la documentación del método File.Exists veo dos problemas:

    – Si la ruta de acceso no es válida el método devuelve false, por lo que intentaríamos crea una ruta no válida.

    – Si el usuario no tiene permisos en la ruta el método también devuelve false, por lo que intentaríamos crear un fichero en una ruta en la que no tenemos permisos.

    Saludos.

  5. Pues como no metas el File.Create en un using o recojas el stream en una variable para poder escribir en él y luego cerrarlo, poco harás… porque el fichero quedará bloqueado hasta que el GC se entere, como muy pronto.

  6. >Pues como no metas el File.Create en un using

    Touché.

    Aunque es cierto todo lo que habéis comentado de permisos y demás, este es el problema que quería comentar. Efectivamente File.Create no se limita a crear el fichero, si no que además devuelve un Filestream para operar con él. Filestream es IDisposable y por lo tanto debemos llamar a su método Dispose.

    Curioso como @Pedro en su comentario ya lo ponía…

    using (FileStream fs = File.Create(fname))
    {
    // resto de cosas
    }

    Incluso si, como en el caso del código que yo estaba mirando, no se requería hacer NADA con el fichero (tan solo crearlo) debemos usar un using:

    using (File.Create(fname))
    {
    // resto de cosas
    }

    O bien, si queremos liberar el fichero en seguida sin esperar a que «resto de cosas» terminen:

    using (File.Create(fname)) ;
    // resto de cosas

    O bien:

    using (File.Create(fname)) { }
    // resto de cosas

    (que es mucho mejor ya que queda claro que el ; final no es un error).

    Un saludo!!! 😉

  7. Al final, algo tan sencillo como pudiera parecer crear un fichero no lo es tanto. Son muchas variables que aparecen ya reflejadas en los comentarios.

    Si existe el fichero, se puede considerar que esté en uso por otro proceso como comentaban. o no sea accesible por permisos, o incluso que esté corrupto (que desde explorador de Windows no se pueda ni borrar).

    Si no existe el fichero, puede ocurrir que no exista la ruta, permisos sobre la ruta no adecuados, que la comprobación-creación del fichero no sea atómica (justo después de la commprobación, otro proceso crea el fichero, díficil pero pudiera darse…) , que no haya espacio en disco suficiente para crearlo, etcétera.

    Saludos.

  8. Hombre Eduard,

    Yo es que soy de los que piensa que un byte es un byte y dejar escapar un chorizo, como que no me gusta:)

    Saludos,

  9. sí, es cierto lo que dice Juan Manuel no obstante ‘dependiendo del contexto’ puede que ese no sea el mayor de los problemas. Lo que yo veo es el clásico patrón tester-doer con todos sus pros y contras. Es decir, en un entorno multihilo o multiproceso esto explota!

    Puede que el archivo no exista al momento del test pero que inmediatamente otro hilo o proceso lo cree y por lo tanto, cuando intentamos crearlo nos salta una excepción enorme como una casa que es justamente lo que queríamos evitar con el test.

    Por eso es que el patrón no me gusta.

  10. @Lucas
    Como siempre contestas a un nivel superior 🙂

    Tienes razón, aunque no es lo que quería apuntar en el post.
    Todo lo que dices del patrón tester, junto con lo que comentaba @Kiquenet es totalmente cierto, y hay maneras mejores de hacerlo.

    Evidentemente podría haber puesto en el post: que el usuario tiene todos los permisos y que eso es una aplicación single-threaded y que todas las rutas existen… Pero eso hubiese evitado comentarios como el tuyo.

    Un placer Lucas!

    pd: Algún día deberíamos (¿deberías? :P) dedicar un post al tester/doer y posibles alternativas!

Responder a kiquenet Cancelar respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *