Come utilizzare le variabili globali in C #?


101

Come dichiaro una variabile in modo che ogni classe (* .cs) possa accedere al suo contenuto, senza un riferimento all'istanza?

Risposte:


123

In C#non è possibile definire vere variabili globali (nel senso che non appartengono a nessuna classe).

Detto questo, l'approccio più semplice che conosco per imitare questa caratteristica consiste nell'usare a static class, come segue:

public static class Globals
{
    public const Int32 BUFFER_SIZE = 512; // Unmodifiable
    public static String FILE_NAME = "Output.txt"; // Modifiable
    public static readonly String CODE_PREFIX = "US-"; // Unmodifiable
}

È quindi possibile recuperare i valori definiti ovunque nel codice (a condizione che faccia parte dello stesso namespace):

String code = Globals.CODE_PREFIX + value.ToString();

Per gestire diversi spazi dei nomi, puoi:

  • dichiarare la Globalsclasse senza includerla in una specifica namespace(in modo che venga inserita nello spazio dei nomi dell'applicazione globale);
  • inserire la corretta direttiva using per recuperare le variabili da un altro namespace.

@Zarathos anche la classe deve essere statica?
kosnkov

4
Beh, non è necessario, ma non vedo perché dovresti istanziarlo.
Tommaso Belluzzo

Se devi istanziare la sua per definizione non più "globale", non fa parte dello stato dell'applicazione
Viking

Salve, quale sarebbe la differenza se non dovessi digitare la parola chiave statica nella classe? Ho solo reso statica la stringa FILE_NAME, ho provato e ha funzionato ancora per me.
Tomer Cahal

1
Senza l'attributo statico la tua classe sarà istanziabile (Globals g = new Globals ()). Non altera il comportamento delle variabili statiche dichiarate all'interno, ma non sembra molto utile.
Tommaso Belluzzo

74

Non esiste una variabile globale in C #. Periodo.

Puoi avere membri statici se vuoi:

public static class MyStaticValues
{
   public static bool MyStaticBool {get;set;}
}

Anche se sono d'accordo, potresti espandere il motivo per cui non esiste una variabile globale in C #? Stavo cercando di pensare a una buona ragione per cui l' staticesempio che hai fornito non può essere considerato una variabile globale.
cregox

3
@cawas perché il concetto stesso di "variabile globale" (sospesa dal nulla, fluttuante nel limbo, non appartenente a nessuna classe) va contro la natura stessa dell'OOP. e C # è strettamente orientato agli oggetti.
Federico Berasategui

Sì, questo è tutto il concetto con cui sono d'accordo. Ma rendendo quel membro statico hai appena creato una sorta di var globale. Come si differenzia dalla var globale che hai detto non esiste? Vorrei vedere un esempio pratico.
cregox

1
Mi sento come se stessi eludendo la mia domanda o non sono chiaro. Ma ho già risposto. Qui: stackoverflow.com/a/20010543/274502
cregox

7
Ora mi rendo conto che ciò che intendevo è che i membri statici sono concettualmente e praticamente variabili globali (tranne forse per quella cosa dell'heap , che fa solo la differenza a meno che tu non stia scrivendo codice non sicuro o facendo una sorta di pesante interazione con codice non gestito ). Quindi non so perché qualcuno dovrebbe dire " non esiste una variabile globale in csharp ". Mi ha confuso molto.
cregox

23

Per prima cosa esamina se hai davvero bisogno di una variabile globale invece di usarla sfacciatamente senza considerare la tua architettura software.

Supponiamo che superi il test. A seconda dell'utilizzo, i Globals possono essere difficili da eseguire il debug con le condizioni di gara e molte altre "cose ​​cattive", è meglio affrontarli da un'angolazione in cui sei pronto a gestire cose così brutte. Così,

  1. Racchiudi tutte queste variabili globali in una singola staticclasse (per la gestibilità).
  2. Avere proprietà invece di campi (= 'variabili'). In questo modo hai alcuni meccanismi per risolvere eventuali problemi con scritture simultanee su Globals in futuro.

Lo schema di base per una tale classe sarebbe:

public class Globals
{
    private static bool _expired;
    public static bool Expired 
    {
        get
        {
            // Reads are usually simple
            return _expired;
        }
        set
        {
            // You can add logic here for race conditions,
            // or other measurements
            _expired = value;
        }
    }
    // Perhaps extend this to have Read-Modify-Write static methods
    // for data integrity during concurrency? Situational.
}

Utilizzo da altre classi (all'interno dello stesso spazio dei nomi)

// Read
bool areWeAlive = Globals.Expired;

// Write
// past deadline
Globals.Expired = true;

4

Una caratteristica utile per questo è using static

Come altri hanno già detto, devi creare una classe per i tuoi globali:

public static class Globals {
    public const float PI = 3.14;
}

Ma puoi importarlo in questo modo per non scrivere più il nome della classe davanti alle sue proprietà statiche:

using static Globals;
[...]
Console.WriteLine("Pi is " + PI);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.