🟪 C# — 2000

⬅️ Atlas · 🗂️ Todas las fichas · 📚 Índice de clases

C# nació como la respuesta de Microsoft a Java y acabó adelantándolo en casi todo lo que significa "características del lenguaje". Es, probablemente, el lenguaje mayoritario que más rápido ha incorporado ideas de la investigación: genéricos reificados, consultas integradas, async/await y tipos que distinguen si algo puede ser nulo.

🎯 Por qué está en este programa

C# es uno de los diez lenguajes del núcleo y el representante de la familia .NET (Atlas): quien entiende la versión C# de una clase reconoce después F# y VB.NET, que comparten con él el mismo tiempo de ejecución, la misma biblioteca y los mismos tipos.

Y aporta al programa dos cosas que ningún otro del núcleo enseña igual: los genéricos reificados —los tipos existen en ejecución, a diferencia de Java (clase 108)— y el origen de async/await, que C# inventó en 2012 y que hoy está en JavaScript, Python, Rust, Kotlin y C++ (clase 134).

Año 2000; 2.0 con genéricos (2005); 5.0 con async (2012); anual desde 2019
Autoría Anders Hejlsberg, Microsoft — antes Turbo Pascal y Delphi
Familia .NET; sintaxis de C, arquitectura influida por Java y por Delphi
Paradigma Multiparadigma: OO, funcional, imperativo y —con LINQ— declarativo
Tipado Estático, nominal y fuerte; genéricos reificados; nulabilidad comprobada
Memoria Recolección de basura, con struct de valor y Span<T> sin copia
Ejecución Bytecode (IL) sobre el CLR, con JIT; también AOT nativo
Estado 🟢 Muy usado, multiplataforma y de código abierto desde 2016

📜 Historia

Microsoft tenía en los noventa un problema con Java: quería usarlo y quería extenderlo, Sun se opuso, y de ahí salió un pleito y la decisión de hacer una plataforma propia.

En 2000 presentó .NET y C#, diseñado por Anders Hejlsberg — la misma persona que había hecho Turbo Pascal y Delphi, y que después dirigiría TypeScript. Esa continuidad se nota: propiedades, eventos y delegados vienen directamente de Delphi (clase 120).

Y desde el principio hubo una decisión que lo separó de Java y que resultó ser la correcta: el CLR se diseñó para varios lenguajes, con un sistema de tipos común. Por eso VB.NET, F# y C# comparten biblioteca e interoperan sin fricción — que es lo que la clase 157 llama ABI definido por la plataforma, igual que ILE en IBM i.

Los hitos:

🏭 Dónde vive hoy

🧠 Lo que enseña y no enseña ningún otro del núcleo

Uno, genéricos reificados (clase 108). En Java, List<String> y List<Integer> son el mismo tipo en ejecución: los genéricos se borran. En C#, no:

var lista = new List<string>();
Console.WriteLine(lista.GetType());        // System.Collections.Generic.List`1[System.String]

El CLR conoce el argumento de tipo, así que se puede preguntar por él, serializar con él y especializar el código para List<int> sin boxing — lo que tiene consecuencias directas de rendimiento (clase 128).

Dos, el origen de async/await (clase 134). C# lo introdujo en 2012 sobre la máquina de estados que el compilador genera, y de ahí lo copiaron casi todos: TypeScript, Python, Rust, Kotlin, Swift y C++20.

Y tres, LINQ, que es la respuesta más elegante que existe al desajuste de impedancia de la clase 170:

var caros = from p in productos
            where p.Precio > 100
            orderby p.Nombre
            select new { p.Nombre, p.Precio };

Esa consulta se comprueba en compilación, y se puede traducir a SQL por un proveedor —Entity Framework— o ejecutarse en memoria. Es la misma idea que las consultas como estructura de Lisp y que sqlpp11 en C++: la consulta es un árbol tipado, no una cadena (clase 153).

🔄 Lo que se ha modernizado

⚙️ Cómo se ejecuta hoy

dotnet run < entrada.txt                    # el comando de la clase 041
dotnet build -c Release
dotnet publish -c Release -p:PublishAot=true    # binario nativo (clase 174)

dotnet format && dotnet test                 # calidad y pruebas (clases 139 y 146)

🧪 El programa de la clase 041 en C#

using System;
using System.Globalization;

// C# sobre el CLR: tipado estático con cultura invariante para el formato.
string[] p = Console.In.ReadToEnd()
    .Split(new[] { ' ', '\t', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);

double precioUnitario = double.Parse(p[0], CultureInfo.InvariantCulture);
int cantidad = int.Parse(p[1], CultureInfo.InvariantCulture);
double descuento = double.Parse(p[2], CultureInfo.InvariantCulture);

double subtotal = precioUnitario * cantidad;
double total = subtotal * (1 - descuento);

Console.WriteLine("Total: " + total.ToString("F2", CultureInfo.InvariantCulture));

Lo que hay que ver.

📚 Fuentes y bibliografía


⏮️ Volver al Atlas · 🗂️ Todas las fichas · 🔗 Relacionadas: F# · VB.NET · Java · Delphi · TypeScript