Con l’avvento di .NET 10, il panorama dello sviluppo in C# ha accolto una novità tanto attesa quanto rivoluzionaria: le File-Based Apps. Se fino a ieri la creazione di un piccolo tool o di uno script richiedeva la generazione di un’intera struttura di progetto (.csproj), oggi la barriera tra l’idea e l’esecuzione è stata praticamente abbattuta.
In questo articolo esploreremo cosa sono le app basate su file, come funzionano “sotto il cofano” e perché dovresti integrarle nel tuo workflow professionale.
Cosa sono le File-Based Apps?
In termini semplici, una File-Based App è un programma C# contenuto in un singolo file sorgente (.cs) che può essere compilato ed eseguito direttamente, senza la necessità di un file di progetto formale.
Questa funzionalità evolve il concetto di Top-Level Statements (introdotto con C# 9), eliminando la “cerimonia” burocratica delle cartelle e dei file di configurazione per tutti quegli scenari in cui la complessità di una soluzione enterprise sarebbe superflua.
Come funzionano: la magia del .NET SDK
Quando eseguiamo un comando come dotnet my-script.cs, il .NET SDK non si limita a interpretare il codice. Ecco cosa accade nel background:
- Analisi delle Direttive: L’SDK scansiona la parte superiore del file alla ricerca di direttive speciali (precedute da
#:). - Generazione Implicita: Viene creato un progetto temporaneo in memoria o in una cartelle di cache.
- Risoluzione delle Dipendenze: Se sono presenti pacchetti NuGet o riferimenti ad altri progetti, l’SDK li scarica e li collega automaticamente.
- Compilazione ed Esecuzione: Il codice viene compilato (spesso in modalità Native AOT di default per massimizzare le performance) e lanciato.
Anatomia di una File-Based App
La potenza di questo approccio risiede nelle nuove direttive che permettono di mantenere il file “auto-esplicativo”. Ecco i pilastri fondamentali:
#:package <Nome>: Per includere dipendenze NuGet (es.#:package Newtonsoft.Json).#:property <Chiave>=<Valore>: Per impostare proprietà MSBuild (es.#:property TargetFramework=net10.0).#:sdk <Nome>: Per specificare l’SDK di riferimento, come quello Web per micro-servizi rapidi.- Supporto Shebang (
#!): Su sistemi Unix/Linux, permette di rendere il file eseguibile direttamente dal terminale come un normale script Bash o Python.
#!/usr/bin/env dotnet
#:package Spectre.Console@*
using Spectre.Console;
AnsiConsole.Markup("[bold green]Hello World[/] dalle File-Based Apps!");
Perché sono utili nel workflow professionale?
Nonostante la loro semplicità, queste applicazioni non sono “giocattoli”. Ecco i principali vantaggi:
- Scripting di Sistema: C# diventa un serio concorrente di Python e Bash per l’automazione DevOps, con il vantaggio della tipizzazione forte e delle performance di .NET.
- Prototipazione Rapida: Testare un algoritmo o una libreria NuGet diventa immediato. Basta un file e una tastiera.
- Apprendimento e Didattica: Ideali per chi si avvicina al linguaggio, permettendo di focalizzarsi sulla logica senza perdersi nella gestione delle soluzioni di Visual Studio.
- Utility Standalone: Grazie alla compilazione Native AOT predefinita, è possibile generare eseguibili leggeri, veloci e privi di dipendenze esterne in pochi secondi.
Le File-Based Apps non sostituiscono i progetti tradizionali per applicazioni complesse e multi-livello, ma riempiono un vuoto fondamentale nell’ecosistema C#: quello della agilità. Rendono .NET uno strumento versatile non solo per grandi architetture, ma anche per le piccole necessità quotidiane di ogni sviluppatore.
Oltre lo Scripting: Il confronto con Python e PowerShell
Molti sviluppatori si chiedono: “Perché usare C# per piccoli script quando esistono Python o PowerShell?”. La risposta risiede in tre pilastri:
- Type Safety: Avere il controllo dei tipi di C# in uno script riduce drasticamente gli errori a runtime rispetto a Python.
- Performance: Grazie a Native AOT, una File-Based App può essere fino a 10-20 volte più veloce di uno script interpretato.
- Ecosistema Unificato: Puoi riutilizzare le tue librerie aziendali e la tua conoscenza di LINQ e della libreria standard .NET senza dover cambiare contesto mentale.
Caso d’uso: Uno script di Cleanup automatico
Immaginiamo di dover creare un tool che pulisca i log vecchi e invii un report JSON. In passato avresti creato un progetto Console; oggi basta questo singolo file CleanUp.cs:
#:package System.Text.Json
#:property PublishAot=true
using System.IO;
using System.Linq;
using System.Text.Json;
var logPath = "./logs";
var threshold = DateTime.Now.AddDays(-7);
var filesToDelete = Directory.GetFiles(logPath)
.Select(f => new FileInfo(f))
.Where(f => f.LastWriteTime < threshold)
.ToList();
foreach (var file in filesToDelete)
{
file.Delete();
Console.WriteLine($"Eliminato: {file.Name}");
}
// Genera un piccolo report finale
var report = new { TotalDeleted = filesToDelete.Count, Date = DateTime.Now };
File.WriteAllText("report.json", JsonSerializer.Serialize(report));Best Practices e Limitazioni
Sebbene la tentazione di usare un unico file per tutto sia forte, è bene ricordare alcuni punti chiave:
- Modularità: Se il file supera le 500-600 righe, probabilmente è il momento di passare a un progetto
.csprojstandard. - Caching: La prima esecuzione potrebbe essere leggermente più lenta a causa del ripristino dei pacchetti NuGet. Le esecuzioni successive utilizzeranno la cache locale per una velocità istantanea.
- Deployment: Se devi distribuire lo script su server senza .NET installato, usa la direttiva
PublishAot=trueper generare un binario self-contained.