Leía esta mañana –mientras se carga una serie de gráficos en mi actual proyecto- el blog de Marino Posadas que, aunque publica poco, publica bien, y me he quedado más que estupefacto con lo que nos ha contado. He de matizar que en ningún momento dudo de la palabra de Marino, y es por eso por lo que me ha llamado tanto la atención de lo que nos ha contado.
Antes de seguir aquí lo mejor es que leáis su entrada, y volváis a esta.
***
El primer malentendido sobre el texto nos lo ha solucionado el propio Marino en los comentarios: no, Anders no se tiró seis meses para inventar los delegados, sino que estuvo tal tiempo creando el .NET, y durante el cual salió la idea del delegado. Haremos la vista gorda e ignoraremos el hecho de que en Delphi (y C++ Builder) el propio Anders ya tenía algo así.
Además, siempre he dicho que el delegado es el paso siguiente al puntero a función y/o función de retrollamada (o callback, como le se suele citar habitualmente). Eso también queda fuera de toda discusión.
Cuenta Marino que Anders primero analizó que una mayoría de las BSOD en Windows venían a cuenta de drivers defectuosos, y que otra mayoría venía causada por una variación sobre un mismo tema: el moldeo o casting incorrecto de punteros a función, algo que es bastante común en el desarrollo de sistemas.
Por lo tanto, para acabar con el segundo problema, decidió implementar los delegados en .NET. Aquí tenemos la primera falacia de todas, y encima autocontenida. Es decir, los delegados están en .NET, pero no en la creación de drivers, ni en la de software de sistemas, que se sigue haciendo en C++, así que solución, nada de nada.
Claro, a no ser que pensara que el mundo™ iba a abandonar sus millones de líneas de código™ y se iba a pasar derechito al .NET™, acabando en un par de meses con el infierno de los punteros.
Espero que ya se haya dado cuenta de que no, que el .NET está y sirve para lo que está y sirve, y para nada más. Por lo tanto, está claro que no ha acabado con el problema de los punteros locos.
Lo que ha hecho ha sido crear una plataforma de desarrollo en la que se minimiza el problema, pero el código nativo (nuevo y viejo) sigue adoleciendo del mismo. Además, en .NET un delegado vacío, hasta donde llego, lanza una excepción, de igual forma que la ejecución de un puntero a función nulo lanza, también, una excepción, que si eres buen programador, habrás capturado.
***
Vamos ahora a por la segunda falacia. ¿Sabéis qué es en realidad un delegado? Pues un delegado es una clase normal y corriente, pero que está cableada en cierta medida dentro del compilador de C#. De hecho, en C++/CLI podemos usarla como una clase más. Podéis leer algo sobre esto aquí.
¿Y qué hace esa clase? Pues tiene un constructor que viene a recibir un puntero a método o función global. Tiene un método que es el que ejecutará ese puntero recibido. Y tiene una serie de eventos y sobrecarga de operadores que nos permiten la semántica de utilizar “+=” y “-=” para añadir/quitar punteros a función.
Y cuando mandamos ejecutar el delegado, lo que hace es comprobar si el puntero es válido, y si lo es, lo ejecuta. Y si se trata de un delegado multicast, entonces contiene una bolsa de punteros a función que va comprobando que sean válidos y ejecutando uno detrás de otro.
Ni más ni menos.
***
Ahora vamos a lo que vamos, que es la tercera falacia y la más importante de todas. ¿Sabíais que con C++ hacer eso mismo es casi trivial? ¿Sabíais que ya está hecho en Boost (no lo he mirado, pero me apuesto un gallifante a que los hay, y seguro que de varios tipos)? ¿Realmente quería Anders acabar con el tema de los problemas con las funciones de retrollamada? No lo creo, ya que si eso realmente hubiera estado en su agenda, lo que se habría hecho es modificar Win32 para que aceptara un objeto de tipo delegado creado con alguna clase de C++, con un operador puntero para C.
Porque niños, hacer eso mismo en C++ no sólo es trivial, sino mucho más directo, ya que podemos sobrecargar el operador de llamada a función y el de puntero, como nos lo demuestran los predicados de la STL… Pero claro, Anders tiene que barrer para casa y expresar las genialidades de .NET y C#…
En fin…