Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Il linguaggio C# è il più diffuso per la piattaforma .NET, un ambiente di sviluppo open source, gratuito e multipiattaforma. I programmi C# possono essere eseguiti in molti dispositivi diversi: da quelli IoT (Internet delle cose) al cloud e in tutti i dispositivi e le modalità esistenti fra queste due tipologie. È possibile scrivere app per cellulari, computer desktop, computer portatili e server.
C# è un linguaggio per utilizzo generico multipiattaforma che migliora la produttività degli sviluppatori durante la scrittura di codice ad alte prestazioni. Con i suoi milioni di sviluppatori, C# è il linguaggio .NET più diffuso. C# offre un ampio supporto nell'ecosistema e in tutti i carichi di lavoro .NET. In base ai principi orientati agli oggetti, incorpora molte funzionalità di altri paradigmi, non ultima la programmazione funzionale. Le funzionalità di basso livello supportano scenari ad alta efficienza senza scrivere codice non sicuro. La maggior parte del runtime e delle librerie .NET è scritta in C# e i progressi in C# spesso offrono vantaggi a tutti gli sviluppatori .NET.
C# fa parte della famiglia di linguaggi C.
sintassi C# è familiare se è stato usato C, C++, JavaScript, TypeScript o Java. Come C e C++, i punti e virgola (;
) definiscono la fine delle istruzioni. Gli identificatori di C# fanno distinzione tra maiuscole e minuscole. C# usa le stesse parentesi graffe, {
e }
, le istruzioni di controllo, come if
, else
e switch
, e i costrutti di ciclo, come for
e while
. C# include anche un’istruzione foreach
per qualsiasi tipo di raccolta.
Salve, mondo
Il programma "Hello World" viene tradizionalmente usato per presentare un linguaggio di programmazione. Ecco qui in C#:
// This line prints "Hello, World"
Console.WriteLine("Hello, World");
La riga che inizia con //
è un commento a riga singola. I commenti a riga singola di C# iniziano con //
e continuano fino alla fine della riga corrente. C# supporta anche commenti a più righe. I commenti a più righe iniziano con /*
e terminano con */
. Il metodo WriteLine
della classe Console
, che si trova nello spazio dei nomi System
, produce l’output del programma. Questa classe viene fornita dalle librerie di classi standard a cui, per impostazione predefinita, viene fatto automaticamente riferimento in ogni programma C#. Un altro modulo di programma richiede di dichiarare la classe e il metodo contenitore per il punto di ingresso del programma. Il compilatore sintetizza questi elementi quando si usano istruzioni di primo livello.
Questo formato alternativo è ancora valido e contiene molti dei concetti di base in tutti i programmi C#. Molti esempi C# esistenti usano il formato equivalente seguente:
using System;
namespace TourOfCsharp;
class Program
{
static void Main()
{
// This line prints "Hello, World"
Console.WriteLine("Hello, World");
}
}
Il programma "Hello, World" precedente inizia con una direttiva using
che fa riferimento allo spazio dei nomi System
. Gli spazi dei nomi consentono di organizzare i programmi e le librerie C# in modo gerarchico. Gli spazi dei nomi contengono tipi e altri spazi dei nomi: lo spazio dei nomi System
contiene molti tipi, come la classe Console
, a cui viene fatto riferimento nel programma e molti altri spazi dei nomi, come IO
e Collections
. Una direttiva using
che fa riferimento a un determinato spazio dei nomi consente l'uso non qualificato dei tipi che sono membri di tale spazio dei nomi. Grazie alla direttiva using
, il programma può usare Console.WriteLine
come sintassi abbreviata per System.Console.WriteLine
. Nell’esempio precedente, lo spazio dei nomi era incluso in modo implicito.
La classe Program
dichiarata dal programma "Hello World" ha un solo membro, ovvero il metodo denominato Main
. Il metodo Main
viene dichiarato con il modificatore static
. Mentre i metodi di istanza possono fare riferimento a una particolare istanza dell'oggetto contenitore usando la parola chiave this
, i metodi statici operano senza riferimento a un determinato oggetto. Per convenzione, quando non sono presenti istruzioni di primo livello, un metodo statico chiamato Main
funge da punto di ingresso di un programma C#. La classe contenente il metodo Main
è in genere denominata Program
.
Suggerimento
Gli esempi in questo articolo offrono un primo sguardo al codice C#. Alcuni esempi potrebbero mostrare elementi di C# con cui non si ha familiarità. Quando si è pronti per apprendere C#, iniziare con le esercitazioni per principianti oppure approfondire i collegamenti in ogni sezione. Se si ha esperienza in Java, JavaScript, TypeScripto Python, leggere i suggerimenti per trovare rapidamente le informazioni necessarie per apprendere rapidamente C#.
Funzionalità di C# familiari
C# è accessibile ai principianti ma offre funzionalità avanzate per sviluppatori esperti che scrivono applicazioni specializzate. È possibile essere produttivi rapidamente. È possibile apprendere tecniche più specializzate in base alle esigenze delle applicazioni.
Le app C# traggono vantaggio dalla gestione automatica della memoria del runtime di .NET. Le app C# usano anche le librerie di runtime estese fornite dall’SDK .NET. Alcuni componenti sono indipendenti dalla piattaforma, ad esempio librerie di file system, raccolte di dati e librerie matematiche. Altri sono specifici di un singolo carico di lavoro, ad esempio le librerie Web di ASP.NET Core o la libreria dell’interfaccia utente .NET MAUI. Un ecosistema open source avanzato in NuGet augmenta le librerie che fanno parte del runtime. Queste librerie forniscono ancora più componenti che è possibile usare.
C# è un linguaggio fortemente tipizzato. Ogni variabile dichiarata ha un tipo noto in fase di compilazione. Il compilatore o gli strumenti di modifica indicano se si usa il tipo in modo errato. È possibile correggere questi errori prima di eseguire il programma.
Tipi di dati fondamentali sono incorporati nel linguaggio e nel runtime: tipi di valori come int
, double
, char
, tipi di riferimenti come string
, matrici e altre raccolte. Quando si scrivono i programmi, si creano tipi personalizzati. Questi tipi possono essere tipi struct
per valori oppure tipi class
che definiscono il comportamento orientato agli oggetti. È possibile aggiungere il modificatore record
ai tipi struct
o class
in modo che il compilatore sintetizzi il codice per confronti di uguaglianza. È anche possibile creare definizioni interface
, che definiscono un contratto o un insieme di membri, che un tipo che implementa tale interfaccia deve fornire. È anche possibile definire tipi e metodi generici. Quando usato, generics usa parametri di tipo per fornire un segnaposto per un tipo effettivo.
Quando si scrive codice, si definiscono funzioni, chiamate anche metodi, come membri dei tipi struct
e class
. Questi metodi definiscono il comportamento dei tipi. È possibile eseguire l’overload dei metodi con un numero o tipi diversi di parametri. I metodi possono facoltativamente restituire un valore. Oltre ai metodi, i tipi di C# possono avere proprietà, che sono elementi dati supportati da funzioni chiamate funzioni di accesso. I tipi di C# possono definire eventi, che consentono a un tipo di notificare ai sottoscrittori azioni importanti. C# supporta tecniche orientate agli oggetti, ad esempio ereditarietà e polimorfismo per i tipi class
.
Le app C# usano eccezioni per segnalare e gestire errori. Questa procedura è familiare se è stato usato C++ o Java. Il codice genera un’eccezione quando non riesce a eseguire le operazioni previste. Altro codice, indipendentemente dal numero di livelli superiori dello stack di chiamate, può facoltativamente eseguire il ripristino usando un blocco try
- catch
.
Caratteristiche distintive di C#
Alcuni elementi di C# potrebbero essere meno familiari.
C# fornisce la corrispondenza di modelli. Tali espressioni consentono di esaminare i dati e prendere decisioni in base alle relative caratteristiche. Il pattern matching offre un'ottima sintassi per il flusso di controllo basato sui dati. Il codice seguente illustra in che modo i metodi per le operazioni booleane and, or e xor possono essere espresse usando la sintassi dei criteri di ricerca:
public static bool Or(bool left, bool right) =>
(left, right) switch
{
(true, true) => true,
(true, false) => true,
(false, true) => true,
(false, false) => false,
};
public static bool And(bool left, bool right) =>
(left, right) switch
{
(true, true) => true,
(true, false) => false,
(false, true) => false,
(false, false) => false,
};
public static bool Xor(bool left, bool right) =>
(left, right) switch
{
(true, true) => false,
(true, false) => true,
(false, true) => true,
(false, false) => false,
};
Le espressioni di pattern matching possono essere semplificate usando _
come generica per qualsiasi valore. L’esempio seguente illustra come semplificare il metodo and:
public static bool ReducedAnd(bool left, bool right) =>
(left, right) switch
{
(true, true) => true,
(_, _) => false,
};
Gli esempi precedenti dichiarano anche tuple, strutture di dati leggere. Una tupla è una sequenza ordinata e a lunghezza fissa di valori con nomi facoltativi e singoli tipi. Racchiudete la sequenza nei caratteri (
e )
. La dichiarazione (left, right)
definisce una tupla con due valori booleani: left
e right
. Ogni braccio dell'interruttore dichiara un valore di tupla, ad esempio (true, true)
. Le tuple offrono una sintassi pratica per dichiarare un singolo valore con più valori.
Espressioni di raccolta forniscono una sintassi comune per i valori di raccolta. Si scrivono valori o espressioni tra [
e ]
caratteri e il compilatore converte tale espressione nel tipo di raccolta richiesto:
int[] numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
List<string> names = ["Alice", "Bob", "Charlie", "David"];
IEnumerable<int> moreNumbers = [.. numbers, 11, 12, 13];
IEnumerable<string> empty = [];
L'esempio precedente mostra diversi tipi di raccolta che possono essere inizializzati usando espressioni di raccolta. Un esempio usa l'espressione di raccolta vuota []
per dichiarare una raccolta vuota. Un altro esempio usa l'elemento spread ..
per espandere una raccolta e aggiungere tutti i relativi valori all'espressione di raccolta.
È possibile utilizzare le espressioni d'indice e di intervallo per recuperare uno o più elementi da una raccolta indicizzabile.
string second = names[1]; // 0-based index
string last = names[^1]; // ^1 is the last element
int[] smallNumbers = numbers[0..5]; // 0 to 4
L'indice ^
indica dalla posizione finale anziché dall'inizio. L'elemento ^0
è un elemento oltre la fine della raccolta, quindi ^1
è l'ultimo elemento. Il ..
in un'espressione di intervallo indica l'intervallo di elementi da includere. L'intervallo inizia con il primo indice e include tutti gli elementi fino all'ultimo indice, escluso l'elemento all'ultimo indice.
LINQ (Language Integrated Query) fornisce una sintassi comune basata su criteri per eseguire query o trasformare qualsiasi raccolta di dati. LINQ unifica la sintassi per l’esecuzione di query su raccolte in memoria, dati strutturati come XML o JSON, archiviazione di database e persino API dati basate sul cloud. Una volta imparato un insieme di sintassi, sarà possibile cercare e modificare i dati indipendentemente dalla relativa risorsa di archiviazione. La query seguente trova tutti gli studenti la cui media dei punti di voto è maggiore di 3,5:
var honorRoll = from student in Students
where student.GPA > 3.5
select student;
La query precedente funziona per molti tipi di risorse di archiviazione rappresentati da Students
. Potrebbe trattarsi di una raccolta di oggetti, una tabella di database, un BLOB di archiviazione cloud o una struttura XML. La stessa sintassi di query funziona per tutti i tipi di risorse di archiviazione.
Il modello di programmazione asincrona basato su attività consente di scrivere codice che viene letto come se venisse eseguito in modo sincrono, anche se viene eseguito in modo asincrono. Usa le parole chiave async
e await
per descrivere i metodi asincroni e quando un’espressione viene valutata in modo asincrono. L’esempio seguente attende una richiesta Web asincrona. Al termine dell’operazione asincrona, il metodo restituisce la lunghezza della risposta:
public static async Task<int> GetPageLengthAsync(string endpoint)
{
var client = new HttpClient();
var uri = new Uri(endpoint);
byte[] content = await client.GetByteArrayAsync(uri);
return content.Length;
}
C# supporta anche un’istruzione await foreach
per eseguire l’iterazione di una raccolta supportata da un’operazione asincrona, ad esempio un’API di paging GraphQL. L’esempio seguente legge i dati in blocchi, restituendo un iteratore che fornisce l’accesso a ogni elemento quando è disponibile:
public static async IAsyncEnumerable<int> ReadSequence()
{
int index = 0;
while (index < 100)
{
int[] nextChunk = await GetNextChunk(index);
if (nextChunk.Length == 0)
{
yield break;
}
foreach (var item in nextChunk)
{
yield return item;
}
index++;
}
}
I chiamanti possono eseguire l’iterazione della raccolta usando un’istruzione await foreach
:
await foreach (var number in ReadSequence())
{
Console.WriteLine(number);
}
Infine, come parte dell’ecosistema .NET, è possibile usare Visual Studio o Visual Studio Code con C# DevKit. Questi strumenti permettono una comprensione approfondita di C#, incluso il codice che viene scritto. Forniscono anche funzionalità di debug.