Menu

static in C#: classi, metodi, campi e costruttori statici

Cosa significa static in C#: membri che appartengono al tipo invece che a un oggetto, stato condiviso tra le istanze, metodi statici e classi statiche, costruttori statici, const e static readonly, using static e l'errore CS0120.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

static indica un membro che appartiene al tipo, non a un oggetto. Un campo di istanza esiste una volta per ogni oggetto; un campo statico esiste una volta sola, punto. Un metodo di istanza viene eseguito su un oggetto (order.Ship()); un metodo statico viene eseguito sul tipo (Math.Round(x)) e non ha bisogno di alcun oggetto.

Campi statici: una sola copia, condivisa

Il modo più chiaro per vedere la differenza è un contatore. Ogni Order ha il suo Id, ma il numero di ordini creati finora deve stare in un posto condiviso.

Output:

Ana #1, Ben #2, Chen #3
Orders created: 3

Ai membri statici si accede tramite il nome del tipo: Order.Created, non a.Created. C# non permette di raggiungere un membro statico attraverso un'istanza (errore CS0176), e questo rende evidente nel punto di chiamata che il valore è condiviso.

Metodi statici

Un metodo statico non ha this. Lavora solo con i suoi parametri e con altri membri statici. Questo lo rende la forma naturale per le funzioni di supporto che calcolano qualcosa a partire dai loro input:

Output:

61.38 EUR
7

Anche Main è statico: il runtime lo chiama prima che esista qualsiasi oggetto.

L'errore CS0120: codice statico che usa membri di istanza

Poiché Main è statico, chi inizia incontra spesso questo errore appena aggiunge un secondo metodo:

class Program
{
    int visits;
    void Greet() { Console.WriteLine("Hello"); }

    static void Main()
    {
        Greet();    // error CS0120: An object reference is required for the non-static field, method, or property 'Program.Greet()'
        visits++;   // error CS0120: An object reference is required for the non-static field, method, or property 'Program.visits'
    }
}

Un metodo statico non ha un oggetto, quindi non c'è alcun visits da incrementare. Due soluzioni, e quella giusta dipende da cosa è il membro:

  • Il membro è davvero un dato del singolo oggetto: crea un oggetto e usalo. var app = new Program(); app.Greet();
  • Il membro non ha bisogno dello stato dell'oggetto: marcalo come static. static void Greet() { ... }

Marcare tutto come static per far sparire l'errore funziona in un programma minuscolo e diventa stato globale in uno reale. Decidi chiedendoti se il dato appartiene a un oggetto o all'intero programma.

La direzione opposta è sempre consentita: i metodi di istanza possono chiamare liberamente i membri statici.

Classi statiche

Una classe dichiarata static può contenere solo membri statici e non può mai essere istanziata. È un gruppo con un nome di funzioni e costanti.

Output:

77
100
True

Il compilatore fa rispettare il contratto: un membro di istanza dentro una classe statica è l'errore CS0708, e usare new su di essa è l'errore CS0712. Math, Console, File, Path ed Enumerable sono tutte classi statiche. Anche gli extension method devono stare in una classe statica.

Costruttori statici e static readonly

Un campo statico il cui valore richiede più di un'espressione si può impostare in un costruttore statico, che il runtime esegue una sola volta, prima del primo utilizzo del tipo:

Output:

Before first use
ShippingRates initialized
5.50
3
2026-01-01

readonly significa che il campo si può assegnare solo nel suo inizializzatore o nel costruttore statico. Dopo non si può riassegnare, anche se l'oggetto a cui punta potrebbe restare modificabile, ed è per questo che il dizionario è esposto come IReadOnlyDictionary.

const o static readonly

Entrambi ti danno un valore con un nome condiviso da tutto il programma, e differiscono per il momento in cui il valore viene fissato:

conststatic readonly
Valore fissatoin fase di compilazionein esecuzione, una volta
Tipi ammessinumeri, char, bool, string, enum, nullqualsiasi tipo
Implicitamente staticosì (non si può scrivere static const)dichiarato static in modo esplicito
Copiato negli assembly chiamantisìno, viene letto dal campo
Usabile nei switch case e negli argomenti degli attributisìno

La riga sulla copia conta per le librerie: se l'assembly A dichiara public const int MaxItems = 50; e l'assembly B la usa, B contiene il letterale 50. Cambiare A in 100 non ha alcun effetto su B finché B non viene ricompilato. Per valori che potrebbero cambiare tra una versione e l'altra, preferisci static readonly.

using static

Una direttiva using static (C# 6) importa i membri statici di un tipo, così puoi chiamarli senza il nome del tipo:

Output:

Area: 28.27
40

Si legge bene nel codice pieno di calcoli matematici. Altrove usala con moderazione: un WriteLine o un Parse da soli nascondono il tipo da cui arriva il metodo.

Stato statico e thread

Un campo statico è condiviso da tutti i thread del processo. Incrementarlo da più thread contemporaneamente fa perdere aggiornamenti, perché created++ è una lettura, una somma e una scrittura, e due thread possono intrecciarle. Usa Interlocked.Increment(ref created) per i contatori, o un lock per qualsiasi cosa più grande. Le applicazioni web sono il posto dove questo morde di solito: ogni richiesta gira su un qualche thread, quindi un campo statico che contiene "l'utente corrente" è condiviso da tutti gli utenti.

Un'altra sottigliezza: in una classe generica, ogni tipo costruito ha i propri campi statici. Cache<int>.Count e Cache<string>.Count sono due campi diversi.

Quando usare static

Buoni usi:

  • Funzioni di supporto pure che calcolano un risultato dai loro argomenti: formattazione, conversioni, validazione.
  • Costanti e dati di consultazione in sola lettura condivisi dal programma.
  • Metodi factory, come TimeSpan.FromMinutes(5) o il tuo Temperature.FromCelsius(21).
  • Extension method.

Usi sbagliati:

  • Stato globale modificabile (l'utente corrente, un carrello, impostazioni che cambiano). Lega tra loro tutte le parti di codice che lo toccano e fa dipendere i test dagli avanzi degli altri test.
  • Tutto ciò che vorrai sostituire nei test, come un orologio, un database o un servizio che invia email. Le chiamate statiche non si possono sostituire con un fake; un'istanza passata al costruttore sì.

Domande frequenti

Cosa significa static in C#?

Un membro static appartiene al tipo stesso invece che a un oggetto. Di un campo statico esiste una sola copia, qualunque sia il numero di oggetti, e un metodo statico si chiama sul nome del tipo (Math.Max(3, 7)) senza creare un'istanza. Un metodo statico non ha this, quindi non può usare direttamente i campi di istanza.

Cos'è una classe statica in C#?

Una classe dichiarata static può contenere solo membri statici e non può mai essere istanziata (usare new su di essa è l'errore CS0712). Raggruppa funzioni correlate che non hanno bisogno dello stato di un oggetto, come Math, Console o File. Gli extension method devono essere dichiarati in una classe statica.

Come risolvo "An object reference is required for the non-static field, method, or property"?

È l'errore CS0120: un metodo statico, spesso Main, sta usando un membro di istanza. Crea un oggetto e chiama il membro su di esso (var app = new Program(); app.Run();), oppure marca il membro come static se non ha bisogno di dati propri di ogni oggetto.

Che differenza c'è tra const e static readonly in C#?

Una const è una costante in fase di compilazione (numeri, stringhe, bool, enum) il cui valore viene copiato in ogni assembly che la usa. Un campo static readonly viene assegnato una sola volta in esecuzione, nel suo inizializzatore o nel costruttore statico, e può contenere qualsiasi tipo, come un DateTime o una lista. Usa const per i valori che non cambieranno mai, static readonly per tutto il resto.

Quando conviene usare static in C#?

Usa static per il codice che lavora solo sui suoi parametri (funzioni di supporto pure come un formattatore di prezzi), per costanti e cache davvero globali per il programma e per i metodi factory. Evita static per tutto ciò che contiene uno stato per utente o per richiesta, o che vorrai sostituire nei test: lo stato modificabile condiviso è difficile da testare e non è sicuro tra thread senza lock.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA