November 2008 - Artículos

En mi anterior entrada hablé sobre dos curiosidades que he encontrado utilizando el Reflector. En concreto, la que más sensación ha causado ha sido la del uso de goto dentro de la implementación de un método en la biblioteca de .NET. Ciertamente quiero en primer lugar romper una lanza a favor, si no de esos gotos en concreto, sí de su uso.

Con esto no quiero decir que haya que utilizarlo al menos una vez en tus programas, de hecho, la mayoría de los que yo hago no lo usan, pero a veces es, si no completamente necesario, al menos sí recomendable hacerlo. Yo el goto lo uso usaba bastante a menudo dentro de interrupciones en el firmware que hago hacía, y a veces lo utilizo en programas normales de PC.

La situación que yo veo más cercana al uso del salto incondicional para un programa general es la de salir de una intensa anidación de bucles. Imaginemos por un momento que estamos dentro de cuatro o cinco niveles de bucle y que queremos salir desde el interior. Algo así:

Bucle
{
    Bucle
    {
        Bucle
        {
            Bucle
            {
                Salir de todos los bucles
            }
        }
    }
}

Si bien podríamos construir los bucles de forma que la salida fuera automática con una solo break interno (por ejemplo, añadiendo a la condición comparadora de cada bucle una comparación con una posible variable de salida), a veces esto no es posible ya que la comparación o bien depende de datos que sólo están disponibles en la anidación interior o bien el tiempo de comparación en cada iteración es excesivo (hemos de tener en cuenta que a cada iteración de un bucle externo se producen n del interno, por lo que ante x bucles el tiempo de ejecución se acerca a nx). En este caso, una instrucción de salto estaría justificada.

También es cierto que pudiera existir un algoritmo diferente y más sencillo, pero chicos, estamos en el Mundo Real™, y a veces ni podemos ser lo buenos programadores que quisiéramos ni tenemos tiempo para ello.

Otra circunstancia menos habitual (pero que se suele producir con bastante frecuencia en el control de dispositivos) es la de ir adquiriendo recursos o activando elementos de forma secuencial y si en algún momento algo falla, se deben ir recorriendo en secuencia más o menos inversa. Si bien se pueden hacer con una secuencia anidada de sentencias if, a veces no resulta tan sencillo por las características del proceso, por lo que la solución más socorrida es la de, ante un fallo, saltar incondicionalmente al punto de vuelta atrás adecuado.

Todo esto viene al caso de los comentarios expuestos en la entrada anterior. Pues bien, el RFOG, que es más cabezota que un ladrillo ignífugo, ha intentado reproducir un código fuente en C# que termine compilado en algún tipo de goto y no lo ha conseguido. Incluso se ha creado un ejemplo que use dicho método Connect(), pero al parecer el SP1 del .NET Framework 3.5 rompe algo (qué raro) en eso de depurar con el código fuente del .NET, así que no ha podido ver si el fuente original de Microsoft trae o no dichos gotos (Parece ser que es un problema generalizado con el SP1, ya que lo único que aparece si buscas en Internet es que nadie puede depurar a través del fuente de .NET una vez aplicado dicho SP).

Y finalmente, el reto

Bueno, pues el reto es ese: conseguir un código fuente sin gotos que, una vez compilado con C#, genere un código que contenga algún goto visto desde el Reflector. La solución o bien la posteáis como comentario o me la enviáis y pondré las mejores dentro de una nueva entrada.

Yo apuesto en contra, apuesto a que el compilador de C# es tan malo que es incapaz de hacer una optimización más o menos seria de ese tipo. Pero me gustaría que me convencierais de lo contrario.