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.
Suggerimento
Novità dello sviluppo di software? Iniziare prima con le esercitazioni introduttive . Incontrerai le classi quando avrai bisogno di modellare oggetti con comportamento e stato.
Esperienza in un'altra lingua? Le classi C# sono simili alle classi in Java o C++. Esamina la sezione inizializzatori di oggetti per i modelli specifici di C# e vedi Record per un'alternativa incentrata sui dati.
Una classe è un tipo di riferimento che definisce un progetto per gli oggetti. Quando si crea una variabile di un tipo di classe, la variabile contiene un riferimento a un oggetto nell'heap gestito. La variabile non contiene i dati dell'oggetto stesso. L'assegnazione di una variabile di classe a un'altra variabile copia il riferimento, quindi entrambe le variabili puntano allo stesso oggetto. Le classi sono il modo più comune per definire tipi personalizzati in C#. Usarli quando sono necessari comportamenti complessi, ereditarietà o identità condivisa tra i riferimenti.
Quando usare le classi
Usare una classe quando:
- Il tipo ha un comportamento complesso o gestisce lo stato modificabile.
- È necessaria l'ereditarietà per creare una classe base con specializzazioni derivate o per creare un tipo derivato che estende una classe esistente.
- Le istanze rappresentano un'identità condivisa, non oggetti che contengono valori uguali. Due riferimenti allo stesso oggetto devono rimanere sincronizzati.
- Il tipo è di grandi dimensioni o di lunga durata e trae vantaggio dall'allocazione dell'heap e dalla semantica di riferimento.
Dichiarare una classe
Definire una classe con la class parola chiave seguita dal nome del tipo. Un modificatore di accesso facoltativo controlla la visibilità. Il valore predefinito è internal. Specificare public per consentire ai chiamanti di altri assembly di utilizzare i tuoi tipi.
public class Customer
{
public string Name { get; set; }
public Customer(string name) => Name = name;
}
Il corpo della classe contiene campi, proprietà, metodi ed eventi, denominati collettivamente membri della classe. Il nome deve essere un nome di identificatore C# valido.
Creare oggetti
Una classe definisce un tipo, ma non è un oggetto stesso. Si crea un oggetto ( un'istanza della classe) con la new parola chiave :
var customer = new Customer("Allison");
Console.WriteLine(customer.Name); // Allison
La variabile customer contiene un riferimento all'oggetto, non all'oggetto stesso. È possibile assegnare più variabili allo stesso oggetto. Le modifiche tramite un riferimento sono visibili tramite l'altro:
var c1 = new Customer("Grace");
var c2 = c1; // both variables reference the same object
c2.Name = "Hopper";
Console.WriteLine(c1.Name); // Hopper — c1 sees the change made through c2
Questo comportamento di condivisione dei riferimenti è una distinzione tra classi e struct. Con gli struct, l'assegnazione copia i dati. Più importante, le classi supportano l'ereditarietà. È possibile creare gerarchie in cui i tipi derivati riutilizzano e specializzano il comportamento da una classe di base. Le strutture non possono partecipare in gerarchie di ereditarietà. Per altre informazioni sulla distinzione, vedere Tipi di valore e tipi di riferimento.
Costruttori e inizializzazione
Quando crei un'istanza, vuoi che i suoi campi e proprietà siano inizializzati a valori utili. C# offre diversi approcci: inizializzatori di campo, parametri del costruttore, costruttori primari e proprietà obbligatorie.
Gli inizializzatori di campo impostano un valore predefinito direttamente nella dichiarazione di campo:
public class Container
{
private int _capacity = 10;
}
Gli inizializzatori di campo assegnano un valore predefinito ragionevole a un campo o a una proprietà. Questo lo distingue dagli approcci seguenti in cui i chiamanti possono fornire il valore iniziale.
I parametri del costruttore richiedono ai chiamanti di fornire valori:
public class Container
{
private int _capacity;
public Container(int capacity) => _capacity = capacity;
}
I costruttori primari (C# 12+) aggiungono parametri direttamente alla dichiarazione di classe. Questi parametri sono disponibili in tutto il corpo della classe:
public class Container(int capacity)
{
private int _capacity = capacity;
}
I costruttori primari e gli inizializzatori di campo possono interagire: l'inizializzatore _capacity = capacity di campo usa il parametro primary-constructor come valore. Questo modello consente di acquisire argomenti del costruttore in campi con una singola dichiarazione concisa.
Le proprietà obbligatorie impongono che i chiamanti impostino proprietà specifiche tramite un inizializzatore di oggetto:
public class Person
{
public required string FirstName { get; set; }
public required string LastName { get; set; }
}
// var missing = new Person(); // Error: required properties not set
var person = new Person { FirstName = "Grace", LastName = "Hopper" };
Console.WriteLine($"{person.FirstName} {person.LastName}"); // Grace Hopper
Per un'analisi più approfondita dei modelli di costruttore, tra cui la convalida dei parametri e il concatenamento dei costruttori, vedere Costruttori.
Classi statiche
Non è possibile creare un'istanza di una static classe e contiene solo membri statici. Usare classi statiche per organizzare i metodi di utilità che non operano sui dati dell'istanza:
static class MathHelpers
{
public static double CircleCircumference(double radius) =>
2 * Math.PI * radius;
}
double circumference = MathHelpers.CircleCircumference(5.0);
Console.WriteLine($"Circumference: {circumference:F2}"); // Circumference: 31.42
La libreria di classi .NET include molte classi statiche, ad esempio Math e Console. Una classe statica è sigillata in modo implicito. Non è possibile derivarla o crearne un'istanza.
Inizializzatori di oggetto
Gli inizializzatori di oggetti consentono di impostare le proprietà quando si crea un oggetto, senza scrivere un costruttore per ogni combinazione di valori:
class ConnectionOptions
{
public string Host { get; init; } = "localhost";
public int Port { get; init; } = 80;
public bool UseSsl { get; init; }
}
var options = new ConnectionOptions
{
Host = "db.example.com",
Port = 5432,
UseSsl = true
};
Console.WriteLine($"{options.Host}:{options.Port} (SSL: {options.UseSsl})");
// db.example.com:5432 (SSL: True)
Gli inizializzatori di oggetti funzionano con qualsiasi proprietà accessibile che abbia un set o un init accessor. Si combinano naturalmente con required le proprietà e con i costruttori che accettano alcuni parametri consentendo al chiamante di impostare altri.
Quando la proprietà è una raccolta, è possibile usare espressioni Collection (riferimenti C#) per inizializzare tale oggetto.
Ereditarietà
Le classi supportano l'ereditarietà. È possibile definire una nuova classe che riutilizza, estende o modifica il comportamento di una classe esistente. La classe da cui si eredita è la classe base e la nuova classe è la classe derivata:
var manager = new Manager("Satya", "Engineering");
Console.WriteLine($"{manager.Name} manages {manager.Department}");
// Satya manages Engineering
Una classe può ereditare da una classe base e implementare più interfacce. Le classi derivate ereditano tutti i membri della classe base ad eccezione dei costruttori. Per altre informazioni, vedere Ereditarietà e interfacce.