C# public static void main()

Stato
Discussione chiusa ad ulteriori risposte.

dLagoneCinese

Utente Bronze
10 Aprile 2017
14
5
2
31
Non riesco a capire perchè il metodo main è statico, e perchè dovrei creare una un metodo statico (o una variabile statica).
Il manuale in pdf che ho trovato online fa l'esempio del pgreco.
Da questo ho dedotto che si usa per le variabili che devono mantenere sempre lo stesso valore, ma perchè lo devo indicare; insomma alla fine se una variabile durante lo svolgimento del programma si modifica, lo decido io.
Che senso ha castrarla in anticipo, serve per correggere un possibile errore umano?
Ringrazio tutti in anticipo.
 
Ultima modifica:
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]
 
Ultima modifica:
Perfetto, grazie mille.
Riassumendo, in c# se dichiaro che un metodo è statico allora, questo potrà essere richiamato con il nomeClasse.metodo();
(senza dover creare un'instanza)
Allo stesso modo con i campi di una classe (che io chiamavo erroneamente variabili(ops)) nomeClasse.campo;
In fine il discorso più importante:
se determino che un campo di una classe è statico questo farà si che il valore assegnatogli sia lo stesso in tutte le istanze "e non" della classe.( come se tutte le istanze facessero riferimento ad un campo il cui valore era stato assegnato dentro la loro classe ma con il vantaggio di modificarlo in tutte le istanze attraverso una istanza).
Comunque mi è piaciuto il discorso delle costanti. perchè nel mio piccolo i programmi non hanno bisogno di una grande gestione della memoria però non avevo pensato che usare la memoria stuck richiedesse spazio rispetto alla heap, o meglio lo sapevo ma non mi ci ero mai soffermato.
scusate l'italiano ma ho difficolta in questa lingua anche se è l'unica che parlo (-:
Ti ringrazio ancora speedjack per avermi dedicato del tempo.

PS: come hai fatto a mettere il codice dentro le tabelle?
 
Ultima modifica:
C#:
using System;

namespace provaStatic
{
    class MainClass
    {
        public static void Main (string[] args)
        {
   
            // RICHIAMO SENZA ISTANZA:

            altro.ns = 4;

            //RICHIAMO CON ISTANZA:

            altro prova = new altro();


            Console.WriteLine(prova.ns);// ERRORE: impossibile accedere al membro 'provaStatic.altro.ns' con un riferimento a un'istanza.Qualificarlo con un nome di tipo


            // SEZIONE DEDICATA ALLA SPIEGAZIONE DEI METODI:

            int  a = matematica.areaQuadrato(3); // non ho bisogno di creare un'istanza perchè il metodo areaQuadrato è statico.
            Console.WriteLine (a);


            matematica area = new matematica ();  // in questo caso ho dovuto creare un'instanza perchè il metodo non è stato dichiarato statico
             a = area.areaTriangolo(2,3);
            Console.WriteLine(a);

        }
    }


    class altro
    {
        public static int ns;
        public int n;
    }


    class matematica
    {
        public static int areaQuadrato(int n) // metodo statico
        {
            return n * n;
        }

        public  int areaTriangolo(int b, int a) // metodo non statico
        {
            return b*a/2;
   
        }

    }
}
 
OKOK ho scoperto il perchè mi da errore.
Praticamente non si può richiamare un variabile statica con una istanza della classe.Lo puoi utilizzare solo con la classe stessa, e questo spiega il perchè cambia in tutte le istanze."o almeno è più facile da intuire".
infatti se sostituisco Console.WriteLine(altro.ns); nella sezione //RICHIAMO CON ISTANZA:
Il risultato sarà che il programma parte.
 
Ultima modifica:
PS: come hai fatto a mettere il codice dentro le tabelle?
[CODE=nomelang]
...qui il codice...
[/CODE]
dove al posto di "nomelang" metti il nome del linguaggio senza simboli speciali (per C# è "csharp").
Oppure puoi usare le icone dell'editor. Clicki sul simbolo "aggiungi" (il quadratino col + dentro il quadrato vicino al tasto per i video) > "codice".
 
In teoria il main è static in modo che il PC può accedere direttamente alla classe e usare il metodo main senza crearne un istanza e quindi far partire il programma

Inviato dal mio ALE-L21 utilizzando Tapatalk
 
Stato
Discussione chiusa ad ulteriori risposte.