Hai un po' di confusione - e di fatto l'esempio del pi greco è un pessimo esempio, dato che per salvare il valore di pi greco è giusto usare una costante, non una variabile statica.
A maggior ragione per il fatto che C# non supporta le variabili statiche intese come variabili che non vengono distrutte alla fine dell'esecuzione della funzione.
Andiamo con ordine: i linguaggi di programmazione, usano più o meno tutti la keyword
static. In base a dove questa keyword è utilizzata il significato è diverso: il significato di static dipende dal contesto.
In molti linguaggi di programmazione (
non in C#), come in C e C++, static può essere applicata a una variabile per dichiarare una variabile statica, ossia una variabile che mantiene il proprio valore in esecuzioni successive della funzione. Per fare un esempio, in C:
C:
void foo()
{
static int x = 5; /* il valore 5 viene assegnato a x solo la prima volta che foo() viene chiamata */
x = x + 3;
printf("%d", x); /* stampa il valore di x */
}
int main()
{
foo(); /* stampa 8 */
foo(); /* stampa 11 */
foo(); /* stampa 14 */
}
Alla prima chiamata a foo(), a x viene assegnato il valore 5. Quindi viene incrementata di 3 (x prende il valore 8) e poi viene stampata.
Alla seconda chiamata a foo(), x avrà mantenuto (in quanto statica) il valore 8. Quindi viene incrementata di 3 (x prende il valore 11) e poi viene stampata.
Stessa cosa succede alla terza chiamata a foo(), che quindi stampa 14.
Se la variabile x non fosse stata dichiarata statica, a tutte e tre le chiamate a foo() sarebbe stato stampato il valore 8 (5+3).
Se ci pensi un attimo, ti accorgi che una variabile statica in C altro non è che una variabile globale accessibile solo da una funzione e non dalle altre. Di fatto, il compilatore le tratta proprio come variabili globali.
Nota che questo è vero con C, C++ e altri linguaggi - non è invece vero in C# che non supporta le variabili statiche.
In C# invece, si possono avere i campi statici. Ossia (presumo tu sappia cos'è una classe - altrimenti ti mancano troppe conoscenze di base per capire) un campo di una classe può essere dichiarato statico in modo tale che il suo valore sia lo stesso per tutte le istanze di quella classe. Ad esempio:
C#:
class Foo {
static int num; // campo statico
int nonstatic; // campo NON statico
}
// da qualche altra parte nel codice...
Foo A = new Foo(); // creazione di un'instanza di tipo Foo chiamata A
Foo B = new Foo(); // creazione di un'istanza di tipo Foo chiamata B
A.num = 5; // assegno a num di A il valor 5
Console.WriteLine(B.num); // stampa 5 (num, essendo statica, è condivisa tra tutte le istanze)
B.num = B.num + 3; // somma 3 a B.num
Console.WriteLine(A.num); // stampa 8
Console.WriteLine(B.num); // stampa sempre 8
Console.WriteLine(Foo.num); // stampa ancora 8 (si può accedere ai campi statici anche senza aver istanziato la classe)
A.nonstatic = 3;
B.nonstatic = 5;
Console.WriteLine(A.nonstatic); // stampa 3 (stamperebbe 5 se nonstatic fosse statica)
Console.WriteLine(B.nonstatic); // stampa 5
Ancora: è possibile creare metodi (funzioni) statici (un esempio è il metodo main() di cui parlavi). In questo caso, il metodo può essere richiamato senza dover istanziare la classe (non è molto diverso, in fondo, dai campi statici).
C#:
class Foo {
static void staticfunc() { } // membro statico
void nonstatic() { } // membro NON statico
}
// da qualche altra parte
Foo.staticfunc(); // si può richiamare senza istanziare la classe
Foo A = new Foo();
A.staticfunc(); // oppure si può anche instanziare
Foo.nonstatic(); // errore: per chiamare un membro non statico bisogna istanziare la classe
A.nonstatic(); // ok
La funzione Main deve essere dichiarata statica in modo tale che il Framework .NET possa richiamarla correttamente. Nel momento in cui il tuo programma viene messo in esecuzione, viene eseguito un codice speciale (che non vedi) del framework, che sostanzialmente richiama la tua funzione main in questo modo:
C#:
Program.Main(); // chiamata alla funzione membro statica Main() della classe Program
Se Main() non fosse statica, quel codice darebbe errore (e il programma non parte) in quanto non viene istanziato un oggetto della classe Program.
Si possono infine, definire classi static. In tal caso, la classe non può essere istanziata (niente new Foo()) e tutti i metodi e i campi della classe devono quindi essere static anch'essi.
In tutto ciò, le variabili statiche in C# non sono supportate. O meglio: "variabile statica" in C# è un altro nome per indicare "campi statici" che però sono una cosa diversa dalle variabili statiche di altri linguaggi come il C. Se il tuo libro dice che una variabile statica non può cambiare il suo valore, si confonde probabilmente con qualche altro linguaggio. Inoltre anche in altri linguaggi la definizione sarebbe sbagliata (possono cambiare valore, ma in esecuzioni successive della stessa funzione il loro valore non viene
resettato). Le "variabili" che non cambiano valore sono invece chiamate costanti. Il vantaggio di usare le costanti invece che le variabili non sta solo nella possibilità di errori umani, ma anche nella possibilità di ottimizzazioni del codice da parte del compilatore: le costanti potrebbero essere ad esempio inserite direttamente nel codice, senza doverle ogni volta andare a pescare in una locazione di memoria, migliorando le performance (cioè: il compilatore prende il valore della costante, e lo sostituisce ovunque compare quella costante dentro al codice. Se invece usi una variabile, siccome il valore può cambiare durante l'esecuzione, il tuo codice tutte le volte dovrà riaccedere alla locazione di memoria dove la variabile è salvata, leggere il valore e poi utilizzarlo).
Per completezza: in altri linguaggi static può assumere ulteriori altri significati. Ad esempio, in C, la keyword static applicata ad una funzione, fa si che quella funzione possa essere richiamata solo dal modulo (file) entro il quale si trova. Una cosa simile al "private" del C#. Si potrebbe anche dire di più sulla keyword static: si tratta di una keyword che generalmente modifica il modo in cui il compilatore gestisce la variabile/funzione, dove la salva in memoria, ecc. Ci sono differenze di basso livell
[non dovrei aver sbagliato nulla: ma sono diversi anni che non uso il C#, se avessi detto una cazzata qualcuno mi corregga]