Ejecución de C# Basada en Archivos en .NET 10
[[academy-video-youtube({"vid": "2i0MJDHvJq0", "start_time": "0", "title": "File-Based C# Execution in .NET 10", "creator": "Tim Corey", "length": "13m 36s"})]]
C# siempre ha requerido un archivo de proyecto para ejecutar código. Incluso el "Hello World" más simple necesitaba un .csproj, un Program.cs, y un paso de compilación antes de que algo se ejecutara. Con .NET 10, eso cambia. Ahora puedes escribir un único archivo .cs y ejecutarlo directamente, de la misma manera que ejecutarías un script de Python o un archivo de Node.js.
En su video "Ejecución basada en archivos de C# en .NET 10", Tim Corey recorre cada aspecto de esta característica: ejecutar un archivo independiente, pasar argumentos de línea de comando, agregar paquetes NuGet en línea, publicar en un ejecutable nativo y convertir un archivo en un proyecto completo cuando el alcance supera el formato de archivo único. Si has estado usando aplicaciones de consola para scripts rápidos y prototipos, esto cambia significativamente el flujo de trabajo.
Ejecutando un solo archivo C
[0:40 - 1:48] Tim comienza en VS Code con una carpeta vacía. Sin solución, sin archivo de proyecto, sin plantilla. Él crea un único archivo llamado demo.cs con una línea de código:
Console.WriteLine("Hello World");Console.WriteLine("Hello World");Para ejecutarlo:
dotnet run file demo.csdotnet run file demo.csEse es el flujo de trabajo completo. El comando dotnet run file compila y ejecuta el archivo .cs en un solo paso. No se genera un .csproj intermedio, no se crean carpetas bin o obj. El modelo mental se acerca más a la escritura de scripts que al desarrollo tradicional de C#: escribe un archivo, ejecútalo, ve la salida.
Tim hace una comparación directa con Python y JavaScript, donde la ejecución de un solo archivo siempre ha sido lo predeterminado. .NET 10 lleva a C# a ese mismo territorio mientras mantiene la seguridad de tipos y el rendimiento que hacen atractivo a C# en primer lugar.
Argumentos de línea de comandos y usos implícitos
[1:48 - 3:26] El array args está disponible automáticamente, al igual que lo estaría en un Program.cs estándar con declaraciones de nivel superior. Tim modifica el archivo para aceptar un argumento de nombre:
Console.WriteLine($"Hello {args[0]}");Console.WriteLine($"Hello {args[0]}");Ejecutarlo con un argumento:
dotnet run file demo.cs Timdotnet run file demo.cs TimEsto imprime "Hola Tim". Tim señala que Console.WriteLine funciona sin una declaración using System; porque la ejecución basada en archivos incluye "usings" implícitos por defecto. Este es el mismo comportamiento que las declaraciones al nivel superior introducidas en C# 9, ahora extendido a archivos independientes.
El patrón más amplio que Microsoft ha estado siguiendo es reducir la ceremonia en C# un lanzamiento a la vez. "Global usings", declaraciones de nivel superior, y ahora archivos .cs independientes son todos pasos para hacer que C# sea viable para tareas rápidas que anteriormente requerían scripts de Python o bash.
Agregando entrada de usuario
[3:26 - 5:43] Tim reemplaza el enfoque de argumento con entrada interactiva para demostrar que la ejecución basada en archivos admite el rango completo de patrones de aplicaciones de consola:
Console.Write("What is your name? ");
string name = Console.ReadLine();
Console.WriteLine($"Hello {name}");Console.Write("What is your name? ");
string name = Console.ReadLine();
Console.WriteLine($"Hello {name}");Ejecutar esto solicita una entrada, lee la respuesta e imprime el saludo. La E/S estándar funciona idénticamente a un proyecto completo.
Una limitación que Tim menciona: este modo es estrictamente de un solo archivo. No puedes tener dos archivos .cs referenciándose mutuamente. Si tu código crece al punto donde necesitas múltiples archivos, es hora de convertirlo a un proyecto (cubierto más adelante en el video).
Integrando paquetes NuGet
[5:43 - 7:49] Aquí es donde el enfoque de archivo único se vuelve realmente útil para la escritura de scripts. Puedes hacer referencia a paquetes de NuGet directamente dentro del archivo .cs usando una directiva #r en la parte superior:
#r "nuget:Spectre.Console, 0.54.0"
using Spectre.Console;
Console.Write("What is your name? ");
string name = Console.ReadLine();
AnsiConsole.MarkupLine($"Hello [red]{name}[/]");#r "nuget:Spectre.Console, 0.54.0"
using Spectre.Console;
Console.Write("What is your name? ");
string name = Console.ReadLine();
AnsiConsole.MarkupLine($"Hello [red]{name}[/]");La sintaxis #r "nuget:..." le dice al tiempo de ejecución que descargue y haga referencia al paquete especificado antes de la compilación. Tim usa Spectre.Console para colorear la salida, volviendo el texto del saludo rojo.
No hay comando dotnet add package, ni .csproj para editar, ni paso de restauración. La referencia del paquete vive en el archivo fuente mismo. Para scripts que necesitan un cliente HTTP, un serializador JSON o una biblioteca de formateo, esto elimina el trabajo extra de crear un proyecto solo para incluir una dependencia.
Publicando en un ejecutable nativo
[7:49 - 8:59] Cuando quieres distribuir un script basado en archivos como un binario independiente, el comando de publicación lo maneja:
dotnet publish file demo.csdotnet publish file demo.csEsto produce un ejecutable en la carpeta artifacts. El binario compilado incluye todo lo necesario para ejecutarse, sin requerir .NET SDK en la máquina de destino. Tim señala que las construcciones basadas en archivos utilizan Native AOT por defecto, lo que significa que la salida es un binario único, autónomo, con tiempos de inicio rápidos.
Si Native AOT causa problemas de compatibilidad con una biblioteca específica, puedes deshabilitarlo agregando una directiva de propiedad en la parte superior del archivo (similar a como funciona #r para los paquetes). Para la mayoría de los casos de uso de escritura de scripts, sin embargo, AOT es la opción correcta.
Convirtiendo a un proyecto completo
[8:59 - 10:45] La vía de escape para cuando un script supera al formato de archivo único es el comando de conversión:
dotnet project convert file demo.csdotnet project convert file demo.csEsto genera un archivo .csproj que incluye las referencias de paquetes de NuGet de las directivas #r y mueve el código a una estructura de proyecto estándar. A partir de ese punto, puedes agregar múltiples archivos, configurar ajustes de compilación y usar el sistema completo de proyectos .NET.
Tim enmarca esto como una progresión natural: comienza con un solo archivo para experimentos rápidos, y cuando el alcance se expande, promuévelo a un proyecto sin reescribir nada. Las directivas #r se traducen claramente en entradas <PackageReference> en el .csproj generado.
Notas de AOT nativo y plataforma
[10:45 - 12:42] Por defecto, la ejecución basada en archivos se compila con AOT nativo, produciendo los tiempos de inicio más rápidos posibles. Tim nota que esto es ideal para herramientas CLI y scripts donde el rendimiento en el arranque en frío importa. Si una biblioteca no es compatible con AOT, la característica se puede desactivar con una propiedad a nivel de archivo.
En Linux y macOS, también puedes agregar un hashbang (#!/usr/bin/dotnet run file) en la parte superior del archivo .cs, haciéndolo ejecutable directamente desde el shell sin escribir el prefijo dotnet run file. Esto lleva a C# completamente al ámbito del scripting junto con bash, Python y Ruby.
Conclusión: C# como lenguaje de scripting
[12:42 - 13:05] La característica que Tim destaca como la más impactante es la eliminación de la sobrecarga de proyectos para tareas pequeñas. Las aplicaciones de consola siempre han sido la referencia para experimentos rápidos, scripts de automatización y herramientas únicas. La ejecución basada en archivos elimina el protocolo que hacía que estas se sintieran más pesadas de lo necesario, a la vez que mantenía todas las ventajas (seguridad de tipo, rendimiento, ecosistema NuGet) que hacen que C# valga la pena sobre un lenguaje de scripting.
Conclusión
[13:05 - 13:36] En resumen: la ejecución basada en archivos de .NET 10 te permite ejecutar un único archivo .cs con dotnet run file, hacer referencia a paquetes de NuGet con directivas #r, publicar en un binario nativo con dotnet publish file, y convertir en un proyecto completo con dotnet project convert file cuando superes el formato de un solo archivo. AOT nativo está activado por defecto, y los usuarios de Linux/macOS obtienen soporte de hashbang para la ejecución a nivel de shell.
Para cualquier cosa que uses actualmente una aplicación de consola para prototipar o automatizar, esto merece probarse como una alternativa más liviana.
Consejo de ejemplo: si te encuentras creando aplicaciones de consola solo para probar un paquete NuGet o depurar una llamada API, intenta la ejecución basada en archivos en su lugar. Crea un archivo .cs, añade #r "nuget:PackageName, Version" en la parte superior, escribe tu código de prueba y ejecútalo con dotnet run file. Cuando termines, elimina el archivo. No se requiere limpiar el proyecto.
Mira el video completo en su canal de YouTube y obtén más información sobre los flujos de trabajo modernos de desarrollo en C#.

