Informazioni sulla parola chiave statica

14

Ho una certa esperienza nello sviluppo con Java, Javascript e PHP.

Sto leggendo Step by Step di Microsoft Visual C # 2010 che ritengo sia un ottimo libro su come introdurre il linguaggio C #.

Sembra che abbia problemi a capire la parola chiave static. Da quanto ho capito fino a questo punto se una classe viene dichiarata statica, tutti i metodi e le variabili devono essere statici. Il metodo principale è sempre un metodo statico, quindi nella classe esiste il metodo principale tutte le variabili e i metodi sono dichiarati statici se devi chiamarli nel metodo principale. Inoltre ho notato che per chiamare un metodo statico da un'altra classe non è necessario creare un oggetto di questo puoi usare il nome della classe.

Ma qual è lo scopo effettivo della parola chiave static? Quando dovrei dichiarare variabili e metodi statici?

    
posta Nistor Alexandru 03.09.2012 - 12:12
fonte

6 risposte

14

La parola chiave "statica" in C # fa riferimento a qualcosa nella classe o alla classe stessa, condivisa tra tutte le istanze della classe. Ad esempio, è possibile accedere a un campo contrassegnato come statico da tutte le istanze di quella classe attraverso il nome della classe.

public class SomeObject
{
    //Static Field
    static int Foo = 3;

    //instance field
    private int _Foo2 = 4;

    //instance property
    public int Foo2{get{return _Foo2;}set{_Foo2 = value;}}


    //static factory method
    public static SomeObject CreateSomeObject(int fooValue)
    {
        SomeObject retVal = new SomeObject();
        retVal.Foo2 = fooValue;
        return retVal;
    }

    //Parameterless instance constructor
    public SomeObject()
    {
    }

    public static int Add(int x)
    {
        //Static methods can only deal with local variables, or fields that
        //  are also static in the class.  This one adds x to the static member foo
        return x + Foo;

        //Foo2 is not accessable here!
    }

      //Instance method
    public int AddSomething(int x)
    {
        //Add x to the property value of Foo2
        return x + this.Foo2;

        //Note that Foo *is* accessable here as 'SomeObject.Foo'
    }

}

Posso dire onestamente che non ho mai usato una classe contrassegnata come statica con l'eccezione della creazione di metodi di estensione ( Tutorial rapido sui metodi di estensione ).

In ogni caso, esistono schemi di progettazione specifici per l'utilizzo di metodi statici, come modello di fabbrica e singleton pattern , ma la cosa importante da ricordare è che i metodi statici e i costruttori non gestiscono alcuna istanza specifica di una classe (a meno che tu non passare uno in), in genere per fare calcoli o per fare un confronto tra gli oggetti. Il metodo "Main" a cui ti stai riferendo è sempre statico, ma per vederlo da un diverso punto di vista, leggi questo articolo .

Per continuare con questo, ecco come viene chiamata la differenza tra metodi statici e istanziati, campi e proprietà.

public static void Main(string[] args)
{
    //This is a static method that starts a thread in an application
    // space.  At this point not everything actually has to be static...

    //Here is an instantiation with a parameterless contruction
    SomeObject obj = new SomeObject();

    //Here is an instantiation using a static factory method
    SomeObject obj2 = SomeObject.CreateSomeObject(3);

    //Getting field value from static field
    // Notice that this references the class name, not an instance
    int fooValue1 = SomeObject.Foo;

    //Getting property value from instance
    //  Note that this references an object instance
    int fooValue2 = obj2.Foo2;

    //Instance method must be called through an object
    obj2.AddSomething(4);  //if default constructor, would return 8

    //Static methods must be called through class name
    SomeObject.Add(4); //Returns 7
}

Inoltre, controlla questo post per un approfondimento guarda nelle classi statiche.

    
risposta data 04.09.2012 - 21:17
fonte
17

Ecco il modo di spiegarlo di Joshua Bloch, che trovo geniale come la maggior parte di quello che dice (sì, sono un fan di Joshua Bloch :)). Questo è citato dalla memoria.

Immagina che una classe sia l'equivalente di una stampa blu per una casa. L'immagine quindi che una casa è al progetto come un'istanza della classe è per la classe. Puoi avere una classe (blu-stampa) e più istanze (case) create da essa.

Ora il buon senso impone che la maggior parte delle funzioni / comportamenti che una casa (istanza) può avere / fare, anche se sono dichiarati nella stampa blu, non possono essere utilizzati fino a quando una casa reale (istanza) non è composta da quella stampa blu (classe). Ad esempio, la tua stampa blu potrebbe contenere al suo interno il luogo in cui la luce si accende e le lampadine dovrebbero andare, ma non hai modo di farle funzionare sulla stampa blu, devi effettivamente costruire la casa per poter accendi e spegni l'interruttore della luce e accendi e spegni determinate lampadine.

Tuttavia, potresti avere un comportamento che è applicabile direttamente alla stampa blu e che potresti utilizzare / accedere direttamente alla stampa blu senza dover creare una casa reale con quella stampa blu. Immagina che la tua stampa blu abbia un pulsante che, premendo, mostrerà l'impronta della casa contenuta in quella stampa blu (calcolando tutte le lunghezze delle pareti e così via). Ovviamente si potrebbe costruire una casa prima, quindi andare in giro a misurare il suo ingombro, ma è possibile farlo con la sola stampa blu, quindi sarebbe più utile avere questo comportamento implementato nella stampa blu. Tale pulsante incorporato con la stampa blu che calcola l'impronta della casa equivale ad avere una funzione statica in una classe.

    
risposta data 03.09.2012 - 12:36
fonte
10

Guardarlo in questo modo mi aiuta:

  • Ogni tipo ha un'istanza statica.
  • L'istanza statica viene creata al primo accesso al tipo, tramite l'istanza statica o creando un'altra istanza.
  • Puoi creare tutte le istanze non statiche che desideri, ma esiste solo un'istanza statica.
  • Qualunque cosa all'interno di una classe dichiarata come statica appartiene all'istanza statica e quindi non ha accesso ad altre istanze create. Ma le altre istanze hanno accesso all'istanza statica.
  • Se una classe viene dichiarata come statica, non è possibile creare altre istanze, solo l'istanza statica può mai esistere.
  • È possibile dichiarare un costruttore statico per l'istanza statica proprio come un costruttore per un'istanza normale (ma dichiarandolo statico).

Per quanto riguarda quando utilizzare la parola chiave static:

  • Qualsiasi metodo che non ha bisogno di accedere alle proprietà locali può e probabilmente dovrebbe essere dichiarato statico.
  • Le classi di aiuto che non hanno alcuno stato (che dovrebbe essere comunque raro) e che non saranno mai derise possono essere dichiarate statiche. Se dovrebbero essere un'altra questione; utilizzare questa funzionalità con parsimonia.
  • Le proprietà ei campi a cui è necessario accedere da tutte le istanze di una classe devono essere dichiarati statici. Ma usalo solo quando non c'è altra opzione.
risposta data 03.09.2012 - 12:20
fonte
2

La spiegazione più semplice --- Statico = > Esisterà una sola copia per ambiente.

Quindi all'interno di una VM o di un CLR ci sarà sempre una sola copia di una classe statica, e qualsiasi altra classe che fa riferimento dovrà condividere i suoi metodi e dati con tutte le altre classi che la fanno riferimento.

Per una variabile statica, ci sarà solo un'istanza di questa variabile nell'ambiente di runtime, indipendentemente dal numero di copie della classe proprietaria che vengono create quando fanno riferimento a una variabile statica, faranno tutti riferimento allo stesso pezzo di memoria. / p>     

risposta data 18.05.2015 - 18:16
fonte
1

I membri statici sono associati alla Classe, non a nessuna istanza di quella Classe.

Dato che stiamo parlando di .Net, prendi in considerazione la classe String , in particolare i metodi Split e Iscriviti .

Split è un metodo istanza . Crea una variabile String, dagli un valore e puoi chiamare Split () su quella variabile / valore e recuperare un array di "bit":

String s1 = "abc,def,ghi" ; 
String[] array2 = s1.Split( ',' ) ; 

Quindi, per esempio i metodi, il valore contenuto nell'istanza della classe data conta .

Join è un metodo statico . OK, produce un risultato di String quando viene fornito un delimitatore e un array di String da masticare, quindi è "qualcosa a che fare con" la Classe String, ma è non associato con qualsiasi particolare valore in qualsiasi istanza String (infatti, i valori dell'istanza non sono disponibili per i metodi statici).
In altre lingue, il metodo Join potrebbe essere stato "bloccato" sulla classe Array (o, forse meglio, su una classe StringArray) ma i nostri amici di Redmond hanno deciso che era più "rilevante" per la classe String, quindi l'hanno messo lì .

String[] array3 = { ... } 
s1 = String.Join( array3, "," ) ; 

Un'altra alternativa avrebbe potuto essere un metodo di istanza Join, in cui il valore contenuto all'interno della [istanza di classe] String usava il delimitatore di unione, qualcosa del tipo:

// Maybe one day ... 
String s4 = "," ; 
s1 = s4.Join( array3 ) ; 
    
risposta data 18.05.2015 - 13:27
fonte
1

La parola chiave static può essere un po 'difficile da comprendere per i neofiti. Il suo scopo principale è quello di identificare un membro della classe come non appartenente a una singola istanza della classe, ma piuttosto alla classe stessa.

Senza entrare troppo nel dettaglio, C # (e Java) impongono rigidamente l'ideale orientato agli oggetti che tutto il codice e i dati devono appartenere a un oggetto, e quindi è limitato in ambito, visibilità e durata. Questa è generalmente la migliore pratica ovunque si applichi il principio fondamentale di un oggetto che rappresenta una cosa del mondo reale. Tuttavia, non sempre; a volte ciò di cui hai bisogno è una funzione o una variabile che puoi ottenere da ovunque nel codice, senza che tu debba passare un riferimento a un oggetto che lo contiene e con la garanzia che i dati che stai cercando ao cambiare è esattamente ciò che tutti gli altri hanno a che fare, e non una copia di esso appartenente a una diversa istanza di un oggetto.

Tale comportamento era disponibile in C e C ++ sotto forma di funzione o variabile "globale", che non era incapsulato in un oggetto. Quindi, come compromesso, C # e Java supportano "scope statico", un punto a metà tra il codice veramente globale con nessun oggetto principale e membri di istanze con ambito limitato.

Qualsiasi "membro di codice" (funzione, proprietà, campo) dichiarato come static rientra nell'ambito della prima riga della funzione main() del programma e non lo lascia finché la funzione main() non termina. In inglese semplice, esiste un membro statico che può essere utilizzato fino a quando il programma è in esecuzione. Inoltre, i membri statici vengono richiamati chiamandoli come membri del tipo stesso, non membri di una qualsiasi istanza di quel tipo:

public class Foo
{
   public int MyInt {get;set;} //this is an "instance member"
   public static int MyStaticInt {get;set;} //this is a "static member"
}

...

var myFoo = new Foo();
myFoo.MyInt = 5; //valid
myFoo.MyStaticInt = 5; //invalid; MyStaticInt doesn't belong to any one Foo

Foo.MyInt = 5; //invalid; MyInt only has meaning in the context of an instance
Foo.MyStaticInt = 2; //valid

Questo rende i membri statici visibili a qualsiasi codice che abbia conoscenza del tipo, indipendentemente dal fatto che siano a conoscenza di una singola istanza.

Per rispondere alla tua domanda, il vantaggio principale di contrassegnare qualcosa come statico è che diventa visibile ovunque sia noto il tipo stesso, indipendentemente dal fatto che il codice di consumo abbia o possa ottenere un'istanza dell'oggetto contenente. C'è anche un lieve vantaggio in termini di prestazioni; poiché il metodo è in ambito statico, può solo accedere ad altri membri statici (della stessa classe o di altri) e qualsiasi cosa venga passata come parametro. Pertanto, il runtime non deve risolvere alcun riferimento all'istanza corrente dell'oggetto contenitore, come normalmente dovrebbe fare per un metodo di istanza al fine di fornire informazioni sullo stato specifiche del contesto.

Anche intere classi possono essere contrassegnate come statiche; così facendo, dici al compilatore che la dichiarazione di classe sarà composta esclusivamente da membri statici e quindi non può essere istanziata. Questo è un modo semplice per assicurarsi che ci sia una sola copia di un oggetto in memoria; rendere la classe e tutto ciò che è statico. Tuttavia, è molto raro che questa sia la soluzione migliore a tale necessità. In una situazione in cui è richiesta esattamente una sola copia di un insieme di dati, il "singleton" viene in genere consigliato; questa è una classe non statica, che utilizza un accessorio statico e un costruttore non pubblico per fornire l'accesso a una singola istanza di se stesso. In teoria, un singleton offre gli stessi vantaggi di una classe completamente statica, ma con la capacità aggiuntiva di utilizzare la classe in un modo basato sull'istanza e orientato agli oggetti.

    
risposta data 17.11.2014 - 21:57
fonte

Leggi altre domande sui tag