Más cosas curiosas sobre el C#

    Voy a comentar más cosas curiosas que estoy descubriéndole al C# y que quizás los expertos del lenguaje vean como obvias, pero que personalmente considero son bastante interesantes. Vamos allá.


La sentencia switch 
    Esta sentencia es muy curiosa (y muy potente, quizás más que su equivalente en C++). Lo más curioso de todo es que se puede utilizar una cadena (del tipo string como valor comparativo. Algo así:


switch(miCad)
{
    case «Hola»: 
        break; 
    case «Adiós»: 
        break; 
    default: 
        break;
}


    Y no es una característica pobre el poder hacer esto, que tradicionalmente se suele hacer mediante la concatenación de condicionales.


    Otra cosa curiosa es la imposibilidad de «caer a través» de un case, lo que si en principio puede parecer una limitación, realmente no lo es, porque existe una forma correcta de «caer» y que, al contrario que con otros lenguajes, no es propenso a cometer errores. Porque amigos, el error más común en una sentencia swtich es que se te olvide un break, y dicho olvido puede causar interesantes efectos laterales no deseados que pueden causar una buena tanda de problemas. Veamos un ejemplo:


switch(f)

    case 1: 
        CasoUno();    //Error, falta break 
    case 2:
        CasoDos(); 
        goto default; 
    case 3: 
        CasoTres(); 
        break; 
    case 4: 
        CasoCuatro(); 
        goto case 2; 
    case 5: 
    default: 
        break;
}


Menuda máquina de estados, está más liada que el pelo de un indigente. En el caso 1 tenemos un error, pues estamos «cayendo» sobre el caso 2. En el 2, tras ejecutar el método, saltamos al caso por defecto. Y finalmente en el caso 4, tras ejecutar el método, volvemos al caso 2. Como cosa curiosa decir que la forma del caso 5 está permitida para agrupar casos con el mismo comportamiento. Muy bonito y muy potente.


Además, los casos no tienen por qué estar ordenados, el compilador ya sabe por cuáles ha pasado y por cuáles no. Menuda gozada.


Alias para espacios de nombres
Con esta característica lo mismo sorprendo a alguien. Seguro. Podemos definir espacios de nombre (namespace) que son alias de otros espacios de nombres. Es un tema curioso y que creo que ni el C++ ni el C++/CLI tienen. Veamos un ejemplo:


namespace N1.N2

    class A{}
}


namespace N3

    using R=N1.N2; 
    class B:R.A{}
}


Observamos que la clase B hereda de la clase A del espacio de nombres N1.N2, pero lo hemos hecho utilizando un alias.


Las reglas de manejo de todo esto están explicadas en las páginas 266 y siguientes del The C# Programming Language que he citado por aquí en otros momentos. Son unas reglas un tanto pejigueras, puesto que no permiten anidación y están limitadas dentro de un espacio de nombres, pero bueno, ahí están para ser utilizadas.


Bloqueos y chequeos
Tenemos dos sentencias que permiten establecer la verificación de los cálculos matemáticos, lo que en ciertas aplicaciones científicas o comerciales pueden ser de gran ayuda. Si colocamos una serie de sentencias dentro de un bloque checked su interior será verificado por el compilador y el entorno de ejecución, generando excepciones en los casos que sea necesario o incluso impidiendo la compilación en los casos en los que la verificación puede comprobarse en tiempo de compilación. Con unchecked hacemos justo lo contrario. Y tenemos estas dos opciones porque podemos decir que nuestro código sea chequeado y tener partes no chequeadas y viceversa en las opciones del proyecto. También hay que tener en cuenta que los bloques verificados se ejecutan más lentos.


Podemos bloquear una variable y ejecutar un bloque de código con dicha variable bloqueada. Es una característica interesante aunque peligrosa si estamos utilizando hilos, porque podríamos bloquear la aplicación indefinidamente si dos hilos bloquean simultáneamente la misma variable, así que hay que andarse con ojo con esta característica, y mejor es utilizar otras opciones de sincronización ofrecidas por el sistema operativo o las bibliotecas de clases.


Me voy
El C# como todo lenguaje que se precie tiene la instrucción goto, aunque aparte del uso ya explicado poco sentido le veo; yo suelo usar goto cuando programo hardware (micros sin sistema operativo, interrupciones físicas, etc.), pero en un lenguaje de alto nivel (o con C/C++ pero en programas de alto nivel) la verdad es que dicha instrucción se desvirtúa.


Usando el uso
Esta característica me gusta poco aunque la considero útil. En mis programas en C++/CLI uso la destrucción determinista, pero en C# no se puede hacer. Para forzar la destrucción de recursos no manejados debemos utilizar la sentencia using, aunque personalmente nunca la he usado… pero no me olvido de cerrar el recurso abierto.


Un ejemplo de libro sobre este uso sería:


Using(TextReader r=File.OpenText(«hola.txt»)) { 
    String s; 
    While((s=r.ReadLine())!=null) { 
        Console.WriteLine(s); 
    }
}


Lo curioso de este ejemplo es que la sentencia while genera un warning en la asignación de s, pero no tiene nada que ver con lo que estamos explicando.

6 comentarios sobre “Más cosas curiosas sobre el C#”

  1. buenas Rafael!

    Muy buen articulo sobre estas «cosillas» tan monas que tiene C#!!!

    Solo un par de comentarios:

    a) en el tema de switch/break, supongo que ya conoces el Duff’s device, una de esas curiosidades programantes que NO se pueden hacer en c#
    http://en.wikipedia.org/wiki/Duff's_device

    b) en tu comentario sobre el using, tengo una anotacion y una duda:
    – La duda es que no se donde deberia dar un warning (creo que la sintaxis esta correcta, que problema te da?)
    – La anotacion es que using tiene de bueno que no solo hace la liberacion de memoria automatica al finalizar, sino que engloba todo el bloque en un try/catch/finally, con lo que libera la memoria incluso en caso de error durante la ejecucion (que es de lo que se olvida la mayoria de la gente) Ademas de funcionar para cualquier IDisposable, claro

    Espero la proxima entrega de tus aventuras en C#

    }:)

  2. Phobeo: ciertamente ya había visto el código del Duff’s device, pero ni se me había pasado por la cabeza que se llamara así… Y desde luego ni me acordé de ello cuando estaba escribiendo esto. Efectivamente, ese código no funciona porque no se permite el «caer» entre sentencias «case», pero podría solucionarse añadiendo «goto case » en donde fuera el siguiente, aunque sobre el rendimiento final nada puedo decir (y estoy perro como para hacer pruebas).

    Respecto a lo del warning, es cierto, no da ninguno… Hace unos meses hice un código similar a ese y me dio uno… Se ve que había algo más en el código, ahora no recuerdo.

    Buena tu anotación. 🙂

  3. Phobeo: ciertamente ya había visto el código del Duff’s device, pero ni se me había pasado por la cabeza que se llamara así… Y desde luego ni me acordé de ello cuando estaba escribiendo esto. Efectivamente, ese código no funciona porque no se permite el «caer» entre sentencias «case», pero podría solucionarse añadiendo «goto case » en donde fuera el siguiente, aunque sobre el rendimiento final nada puedo decir (y estoy perro como para hacer pruebas).

    Respecto a lo del warning, es cierto, no da ninguno… Hace unos meses hice un código similar a ese y me dio uno… Se ve que había algo más en el código, ahora no recuerdo.

    Buena tu anotación. 🙂

  4. Wilson, si te refieres a la instrucción

    While((s=r.ReadLine())!=null)

    está en mayúsculas porque escribo las entradas con Word y éste tiene la mala costumbre de poner las primeras palabras en mayúsclas. Ese While es el while normal de C#.

    Y si te refieres a qué hay dentro es sencillo: el TextReader r lee y asigna una línea al string s, que a su vez se comprueba si no es nulo (cuando un TextReader intenta leer una línea más allá del final del archivo devuelve null, que se asigna al string). Es una forma de detectar el final del fichero.

Responder a rfog Cancelar respuesta

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