Introduzione a C# e alla piattaforma .NET
C# (pronunciato "C sharp") è un linguaggio di programmazione moderno, fortemente tipizzato e orientato agli oggetti, sviluppato da Microsoft e presentato per la prima volta nel 2000 insieme alla piattaforma .NET. Nel corso degli anni è cresciuto fino a diventare uno dei linguaggi più utilizzati al mondo, impiegato per costruire applicazioni desktop, servizi web, API, giochi con Unity, applicazioni mobile con .NET MAUI e software cloud-native. Questo primo articolo introduce il linguaggio, spiega come si colloca all'interno dell'ecosistema .NET e ci accompagna nella scrittura ed esecuzione del primo programma.
Che cos'è C#
C# nasce come linguaggio general-purpose ispirato a C, C++ e Java, ma progettato fin dall'inizio per essere più sicuro e produttivo. Le sue caratteristiche fondamentali sono la tipizzazione statica, la gestione automatica della memoria tramite un garbage collector, il supporto nativo alla programmazione orientata agli oggetti e, nelle versioni più recenti, l'adozione di paradigmi funzionali come le espressioni lambda, il pattern matching e i tipi immutabili.
Il linguaggio si è evoluto di pari passo con la piattaforma su cui gira. Ogni nuova versione introduce feature che semplificano la scrittura del codice: dai tipi generici delle prime versioni fino ai record, ai nullable reference types e ai top-level statements delle release più recenti. Questa serie di articoli parte dalle fondamenta, così da costruire una base solida indipendentemente dalla versione specifica utilizzata.
La piattaforma .NET
C# non vive isolato: è il linguaggio di punta della piattaforma .NET, un ambiente di esecuzione e un insieme di librerie che forniscono tutto ciò che serve per costruire ed eseguire applicazioni. Quando si scrive codice C#, questo non viene compilato direttamente in istruzioni macchina, ma in un linguaggio intermedio chiamato IL (Intermediate Language). Comprendere questo passaggio aiuta a capire come funziona davvero l'esecuzione di un programma.
I componenti principali della piattaforma sono i seguenti:
- CLR (Common Language Runtime): è la macchina virtuale che esegue il codice. Si occupa della compilazione JIT (Just-In-Time) da IL a codice macchina, della gestione della memoria tramite il garbage collector, della sicurezza e della gestione delle eccezioni.
- BCL (Base Class Library): è la libreria standard che offre migliaia di classi pronte all'uso per lavorare con stringhe, collezioni, file, rete, date, thread e molto altro.
- Il compilatore: traduce il codice sorgente C# in un assembly, tipicamente un file con estensione
.dllo.exe, contenente l'IL e i metadati che descrivono i tipi.
Il flusso di esecuzione è quindi in due fasi: il codice sorgente viene prima compilato in IL, poi al momento dell'esecuzione il CLR traduce l'IL in codice macchina nativo per la piattaforma su cui gira. Questo modello rende il codice C# portabile: lo stesso assembly può funzionare su Windows, Linux e macOS grazie alle implementazioni multipiattaforma del runtime.
Installare l'SDK
Per sviluppare in C# è necessario installare l'SDK di .NET, che include il compilatore, il runtime e lo strumento a riga di comando dotnet. Una volta installato, è possibile verificare la versione disponibile con un comando da terminale:
dotnet --version
Lo strumento dotnet è il centro di controllo per creare, compilare, eseguire e pubblicare i progetti. Per creare una nuova applicazione console, che è il punto di partenza ideale per imparare il linguaggio, si usa il template console:
dotnet new console -o HelloWorld
cd HelloWorld
Questo comando genera una cartella con la struttura minima di un progetto: un file di progetto con estensione .csproj, che descrive la configurazione e le dipendenze, e un file Program.cs che contiene il codice iniziale.
Il primo programma
Aprendo il file Program.cs appena generato, troviamo un programma minimale. Nelle versioni recenti di C# è possibile scrivere codice usando i cosiddetti top-level statements, che eliminano gran parte della struttura ripetitiva richiesta in passato:
// Program.cs
// Stampa un messaggio sulla console
Console.WriteLine("Ciao, mondo!");
Questo è un programma C# completo e funzionante. La classe Console, fornita dalla BCL, rappresenta il flusso di input e output standard, e il suo metodo WriteLine stampa una riga di testo sul terminale.
Per capire cosa avviene "dietro le quinte" è utile vedere la forma esplicita ed equivalente, che era l'unica disponibile nelle versioni più datate. Ogni programma parte da un metodo speciale chiamato Main, che rappresenta il punto di ingresso dell'applicazione:
// Forma esplicita equivalente
namespace HelloWorld
{
// La classe che contiene il punto di ingresso
class Program
{
// Il metodo Main e il primo codice che viene eseguito
static void Main(string[] args)
{
Console.WriteLine("Ciao, mondo!");
}
}
}
Analizziamo i pezzi principali di questa struttura, perché li ritroveremo continuamente:
- namespace: raggruppa logicamente il codice per evitare conflitti tra nomi. È l'equivalente di uno spazio dei nomi che contiene le classi correlate.
- class: definisce un tipo. In C# quasi tutto il codice vive all'interno di una classe.
- static void Main: è il metodo di ingresso. La parola
staticindica che appartiene alla classe e non a una sua istanza,voidsignifica che non restituisce alcun valore e il parametroargsraccoglie gli eventuali argomenti passati da riga di comando.
Compilare ed eseguire
Con il codice pronto, l'esecuzione è immediata. Dall'interno della cartella del progetto si lancia:
dotnet run
Il comando run compila il progetto se necessario ed esegue l'applicazione, mostrando l'output sul terminale. Durante lo sviluppo è il comando che si usa più spesso. Quando invece si vuole produrre l'assembly senza eseguirlo, si usa dotnet build, mentre per creare una versione distribuibile e ottimizzata dell'applicazione si ricorre a dotnet publish.
La struttura di un progetto
Il file .csproj merita una breve occhiata perché definisce come il progetto viene compilato. Nella sua forma più semplice contiene poche righe:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
La proprietà TargetFramework indica la versione della piattaforma su cui gira l'applicazione, OutputType specifica che si tratta di un eseguibile, mentre ImplicitUsings e Nullable sono opzioni moderne che riducono il codice ripetitivo e aumentano la sicurezza sui riferimenti nulli. Ci occuperemo di questi aspetti nei prossimi articoli.
Conclusione
Abbiamo introdotto C# come linguaggio moderno e la piattaforma .NET come ambiente che lo esegue, chiarendo il ruolo del CLR, della libreria standard e del processo di compilazione in due fasi. Abbiamo installato gli strumenti, creato un progetto console e scritto il classico programma di benvenuto, sia nella forma sintetica con i top-level statements sia in quella esplicita con il metodo Main. Nel prossimo articolo entreremo nel cuore del linguaggio esplorando variabili, tipi di dato e conversioni, i mattoni fondamentali con cui costruiremo tutto il resto.