Historia de C#
C# Versión 1
Cuando echas la vista atrás, la primera versión de C# sí que se parecía un montón a Java. Como parte de sus objetivos de diseño escritos para ECMA, buscaba ser un “lenguaje orientado a objetos de uso general moderno y sencillo”. En aquel momento, podría haber hecho algo peor que mirar hacia Java para alcanzar dichos fines.
Pero si analizases la versión 1.0 de C# 1.0 hoy, te marearías. Carecía de capacidades asíncronas sólidas y de muchas de las “pulidas” funcionalidades relacionadas con los genéricos que hoy en día damos por sentadas. En realidad, carecía de genéricos en general. ¿Y LINQ? Nada. Eso tardaría aún unos cuantos años en salir.
La versión 1 de C# parecía estar bastante desprovista de funcionalidad, comparado con hoy. Al final te veías escribiendo código pesado. Pero bueno, como con cualquier versión 1.0: por algún lado hay que empezar…
C# Versión 2
Aquí las cosas se empiezan a poner interesantes. Repasemos algunas de las principales características de C# 2.0, lanzado en 2005, junto con Visual Studio 2005 (no te olvides de echarle un vistazo al libro escrito por el creador de NDepend, Patrick Smacchia, sobre .NET 2.0, disponible en inglés y francés).
Genéricos
Tipos parciales
Métodos anónimos
Tipos anulables
Iteradores
Covarianza y contravarianza
Aunque Microsoft puede que haya empezado con un lenguaje orientado a objetos bastante genérico, la versión 2 de C# lo cambió todo enseguida. Se pusieron a la tarea tras la salida de la versión inicial y fueron a por varias de las frustraciones que causaba. Y lo hicieron muy en serio.
Con genéricos, tienes tipos y métodos que pueden operar sobre un tipo arbitrario mientras que aún conservan seguridad de tipos. Así, por ejemplo, tener una List<T> te permite tener una List<string> o una List<int> y realizar operaciones seguras de tipo en esas cadenas de caracteres o ints mientras iteras por ellas. Esto es mucho mejor que crear clases derivadas de listas (ListInt?) o convertir a un Objeto para cada operación.
¡Ah!, y hablando de iteradores, la versión 2 de C# los presentó. Para resumir, esto te permite iterar por los ítems de una Lista (u otros tipos Enumerable) con un bucle foreach. Tener esto como un elemento de primera clase del lenguaje mejoró ostensiblemente la legibilidad del código y la capacidad para poder entenderlo.
Y aún así, Microsoft seguía intentando ponerse a la altura de Java. Java ya había liberado versiones que incluían genéricos e iteradores. Pero eso cambiaría pronto a medida que los lenguajes seguían una evolución diferente.
C# Versión 3
La versión 3 de C# apareció a finales de 2007, junto con Visual Studio 2008, aunque la funcionalidad completa aparecería con la versión 3.5 de C#. ¡Y menuda actualización resultó ser!. Yo me atrevería a afirmar que ese momento consolidó a C# como un lenguaje de programación realmente formidable. Veamos algunas de sus características principales en esta versión:
Propiedades auto-implementadas
Tipos anónimos
Expresiones de consulta - LINQ
Expresiones lambda
Árboles de expresión
Métodos de extensión
Con mirada retrospectiva, muchas de estas características parecen tanto inevitables como inseparables. De hecho, no es fácil destacar una sobre otra ya que todas encajan estratégicamente muy bien juntas.
Otros haciendo este mismo análisis no tendrán ese problema, y dirán que, de largo, la novedad más importante de la versión 3 de C# fue las expresiones de consulta, también conocidas como LINQ (Language INtegrated Query).
Yo creo que hay más matices y sutilezas puesto que, desde mi punto de vista, los árboles de expresión, las expresiones lambda y los tipos anónimos fueron los cimientos sobre los que se creó LINQ. Disertaciones aparte, lo cierto es que nos encontramos con un concepto realmente revolucionario. Microsoft había empezado a allanar el terreno para hacer de C# un lenguaje funcional orientado a objetos híbrido.
En concreto, con esta versión ya se podían programar búsquedas declarativas tipo SQL para llevar a cabo operaciones en colecciones, entre otras cosas. En vez de tener que crear un bucle para computar la media de una lista de enteros, ahora se podía hacer con algo tan fácil como list.Average(). La combinación de expresiones de búsqueda y métodos de extensión hizo parecer que las listas de enteros se habían hecho más inteligentes.
Llevó un tiempo hasta que los programadores realmente entendieron cómo integrar el concepto, pero a la larga lo lograron. Y ahora, unos años más tarde, el código es mucho más conciso, sencillo y funcional.
C# Versión 4
La versión 4 de C# nació con el estigma de no suponer una innovación rompedora como sí lo había sido su antecesora versión 3. Y es que con la versión 3, Microsoft hizo que el lenguaje dejase de estar a la sombra de Java y empezó a destacar. Rápidamente el lenguaje se estaba convirtiendo en una opción elegante.
De todos modos, la versión 4 de C# sí introdujo alguna cosas chulas.
Tipos dinámicos
Argumentos opcionales y con nombre
Covarianza y contravarianza genérica
Tipos interop embebidos
Los tipos interop embebidos aliviaron problemas a la hora del despliegue. La covarianza y contravarianza genéricas te dan mucha potencia, pero son demasiado académicas y probablemente sean más valoradas entre los creadores de frameworks y bibliotecas. Los argumentos opcionales y con nombre te permiten eliminar muchas sobrecargas de método y ofrecen comodidad. Pero ninguna de estas cosas altera el paradigma propiamente dicho.
Esa distinción sí se la llevan los tipo dinámico. Con esta característica, Microsoft introdujo en la versión 4 de C# la capacidad de anular el compilador al tiparlo en tiempo de compilación. Es decir, al usar el tipo de referencia dinámico, te puedes llegar a pegar un tiro en el pie como en los lenguajes de tipado dinámico como JavaScript. Puedes crear una “x = cadena de caracteres” dinámica y luego añadirle 6, dejando al tiempo de ejecución determinar qué diablos tiene que pasar después.
Esto lo digo un poco de broma obviamente. Está claro que cabe la posibilidad de cometer errores, pero también otorga mucha potencia dentro del lenguaje.
C# Versión 5
Con la versión 5 de C#, Microsoft liberó una versión con el foco muy puesto en la innovación del lenguaje. Esta es la lista de las características más importantes:
Programación asincrónica con Async y Await
Atributos Caller info
No quiero que se me malinterprete. El atributo caller info está muy bien. Te permite recuperar información sobre el contexto en el que estás sin tener que recurrir a un montón de código reflejo repetitivo. Me encanta esta funcionalidad en realidad.
Pero async y await son las verdaderas estrellas de esta versión. Cuando esto salió en 2012, Microsoft cambió las reglas del juego nuevamente al meter la asincronía en el lenguaje como un participante de primera clase. Si ya has gestionado operaciones largas y la implementación de páginas web con retro-llamadas, probablemente adores esta funcionalidad.
C# Versión 6
Con las versiones 3 y 5, Microsoft había hecho algunas cosas bastante impresionantes en un lenguaje orientado a objetos (la versión 2 también, pero estaban copiando conceptos de Java con esas funciones que introdujeron). Con la versión 6 se alejaron de la idea de sacar una novedad dominante estrella y, en vez de eso, liberaron muchas características para hacer felices a los usuarios del lenguaje de programación. Aquí enumero unas cuantas:
Importaciones estáticas (como en Java)
Filtros de excepciones
Inicializadores de propiedad
Miembros con una expresión como cuerpo
Propagador null
Cadenas interpoladas
Operador nameof
Inicializador del diccionario
Si las vemos de forma individual, todas estas características del lenguaje son muy interesantes. Pero si las valoramos en conjunto, observamos un patrón que nos llama la atención. En esta versión, Microsoft se ha esforzado en eliminar repeticiones en el lenguaje y hacer que el código sea más ligero y legible. Así que para los aficionados del código escueto y limpio, esta versión del lenguaje fue una gran victoria.
¡Ah!, e hicieron otra cosa con esta versión, aunque no se puede considerar como una función tradicional del lenguaje, per se. Liberaron Roslyn, el compilador, como servicio. Microsoft ahora usa C# para hacer C#, y te dejan usar el compilador como parte de tus esfuerzos de programación.
C# Versión 7
Finalmente hemos llegado ya a la versión 7 de C#. Es la versión actual en la fecha que se ha escrito este artículo. Tiene cosas muy chulas y revolucionarias que ya estaban en el ADN de la versión 6, pero sin el compilador como servicio. Aquí van las novedades de esta versión:
Variables out
Tuplas y deconstrucción
Coincidencia de patrones
Funciones locales
Extensión de la funcionalidad de miembros con una expresión como cuerpo aparecida en C# 6
Referencias locales y devoluciones
Todas ofrecen nuevas capacidades para que los desarrolladores puedan escribir código más limpio que nunca. En concreto, creo que Microsoft ha dado solución a problemas que venían desde muy lejos al condensar la declaración de variables que se pueden a usar con la palabra clave out y al permitir valores de devolución múltiples vía tuplas.
Además, Microsoft le está dando un uso más amplio al lenguaje. .NET ahora va dirigido a cualquier sistema operativo y tiene la vista puesta de forma firme en la nube y en la portabilidad. Esto es lo que más ocupa la mente y el tiempo de los diseñadores del lenguaje, además de pensar en nuevas características.
Conozco C# desde hace 15 años, y el lenguaje ha estado bajo desarrollo más tiempo que eso. Será emocionante ver qué funcionalidades y características deparará el futuro.
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?