C # – Winforms – Variabili globali

Voglio che alcune variabili siano globali nel progetto e accessibili in ogni forma. Come posso fare questo?

si puoi usare la class statica. come questo:

static class Global { private static string _globalVar = ""; public static string GlobalVar { get { return _globalVar; } set { _globalVar = value; } } } 

e per usare qualsiasi dove tu possa scrivere:

 GlobalClass.GlobalVar = "any string value" 

Oppure puoi inserire le tue globali nell’app.config

È ansible utilizzare la class statica o il modello Singleton .

Senso unico,

Solution Explorer> Il tuo progetto> Proprietà> Impostazioni. Impostazioni. Fare clic su questo file e aggiungere definire le impostazioni dall’IDE.

Accedili da

 Properties.Settings.Default.MySetting = "hello world"; 
 public static class MyGlobals { public static string Global1 = "Hello"; public static string Global2 = "World"; } public class Foo { private void Method1() { string example = MyGlobals.Global1; //etc } } 

Il consenso qui è di mettere le variabili globali in una class statica come membri statici. Quando si crea una nuova applicazione Windows Form, di solito viene fornita con una class Program (Program.cs), che è una class statica e funge da punto di accesso principale dell’applicazione. Vive per tutta la vita dell’app, quindi penso che sia meglio mettere le variabili globali lì invece di crearne una nuova.

 static class Program { public static string globalString = "This is a global string."; ///  /// The main entry point for the application. ///  [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } } 

E usalo come tale:

 public partial class Form1 : Form { public Form1() { Program.globalString = "Accessible in Form1."; InitializeComponent(); } } 

Se si utilizza Visual C #, è sufficiente aggiungere una class in Program.cs che eredita Form e modificare tutta la class ereditata da Form alla class in ogni Form * .cs.

 //Program.cs public class Forms : Form { //Declare your global valuables here. } //Form1.cs public partial class Form1 : Forms //Change from Form to Forms { //... } 

Naturalmente, potrebbe esserci un modo per estendere la class Form senza modificarla . Se è così, tutto ciò che devi fare è estenderlo! Poiché tutti i moduli lo ereditano di default, quindi tutti gli oggetti di valore dichiarati in esso diventeranno automaticamente globali! In bocca al lupo!!!

Hanno già risposto come utilizzare una variabile globale.

Ti dirò perché l’uso delle variabili globali è una ctriggers idea come risultato di questa domanda condotta in stackoverflow in spagnolo.

Traduzione esplicita del testo in spagnolo:

Impatto del cambiamento

Il problema con le variabili globali è che creano dipendenze nascoste. Quando si tratta di applicazioni di grandi dimensioni, tu stesso non sai / ricordi / sei chiaro riguardo agli oggetti che hai e alle loro relazioni.

Quindi, non puoi avere una nozione chiara di quanti oggetti la tua variabile globale sta usando. E se vuoi cambiare qualcosa della variabile globale, ad esempio, il significato di ciascuno dei suoi possibili valori, o il suo tipo? Quante classi o unità di compilazione influiranno sul cambiamento? Se la quantità è piccola, può valere la pena apportare la modifica. Se l’impatto sarà grande, potrebbe valere la pena cercare un’altra soluzione.

Ma qual è l’impatto? Poiché una variabile globale può essere utilizzata ovunque nel codice, può essere molto difficile misurarla.

Inoltre, cerca sempre di avere una variabile con il tempo di vita più breve ansible, in modo che la quantità di codice che fa uso di quella variabile sia il minimo ansible, e quindi meglio capire il suo scopo e chi lo modifica.

Una variabile globale dura per la durata del programma e, quindi, chiunque può utilizzare la variabile, leggerla o, peggio ancora, modificarne il valore, rendendo più difficile sapere quale valore avrà la variabile in ogni dato programma punto. .

Ordine di distruzione

Un altro problema è l’ordine di distruzione. Le variabili vengono sempre distrutte in ordine inverso rispetto alla loro creazione, siano esse variabili locali o globali / statiche (un’eccezione sono i tipi primitivi, int , enum s, ecc., Che non vengono mai distrutti se sono globali / statici finché non terminano programma).

Il problema è che è difficile conoscere l’ordine di costruzione delle variabili globali (o statiche). In linea di principio, è indeterminato.

Se tutte le variabili globali / statiche si trovano in una singola unità di compilazione (ovvero, si ha solo un file .cpp ), l’ordine di costruzione è uguale a quello di scrittura (ovvero le variabili definite in precedenza sono state create in precedenza).

Ma se hai più di uno .cpp ciascuno con le sue variabili globali / statiche, l’ordine di costruzione globale è indeterminato. Ovviamente, l’ordine in ciascuna unità di compilazione (ogni .cpp ), in particolare, è rispettato: se la variabile globale A è definita prima di B , A sarà costruita prima di B , ma è ansible che tra le variabili A e B dell’altro .cpp sono inizializzati. Ad esempio, se si dispone di tre unità con le seguenti variabili globali / statiche:

Image1

Nell’eseguibile potrebbe essere creato in questo ordine (o in qualsiasi altro ordine purché l’ordine relativo sia rispettato all’interno di ogni .cpp ):

image2

Perché questo è importante? Perché se ci sono relazioni tra diversi oggetti globali statici, per esempio, che alcuni usano gli altri nei loro distruttori, forse, nel distruttore di una variabile globale, usi un altro object globale da un’altra unità di compilazione che risulta essere già distrutta (avere stato costruito più tardi).

Dipendenze nascoste e * casi di test *

Ho cercato di trovare la sorgente che userò in questo esempio, ma non riesco a trovarla (comunque, è stato per esemplificare l’uso di singleton, anche se l’esempio è applicabile a variabili globali e statiche). Le dipendenze nascoste creano anche nuovi problemi relativi al controllo del comportamento di un object, se esso dipende dallo stato di una variabile globale.

Immagina di avere un sistema di pagamento, e vuoi testarlo per vedere come funziona, dal momento che è necessario apportare modifiche e il codice proviene da un’altra persona (o la tua, ma da alcuni anni fa). Si apre un nuovo main e si chiama la funzione corrispondente dell’object globale che fornisce un servizio di pagamento bancario con una carta, e si scopre che si inseriscono i dati e si addebita. Come, in un semplice test, ho usato una versione di produzione? Come posso fare un semplice test di pagamento?

Dopo aver chiesto ad altri colleghi di lavoro, risulta che devi “contrassegnare true”, un bool globale che indica se siamo in modalità test o meno, prima di iniziare il processo di raccolta. L’object che fornisce il servizio di pagamento dipende da un altro object che fornisce la modalità di pagamento e tale dipendenza si verifica in modo invisibile per il programmatore.

In altre parole, le variabili globali (o singletones) rendono imansible passare alla “modalità test”, dal momento che le variabili globali non possono essere sostituite da “testare” le istanze (a meno che non si modifichi il codice in cui tale codice viene creato o definito). variabile globale, ma assumiamo che i test siano eseguiti senza modificare il codice madre).

Soluzione

Questo viene risolto mediante la cosiddetta * dipendenza da iniezione *, che consiste nel passare come parametro tutte le dipendenze che un object ha bisogno nel suo costruttore o nel metodo corrispondente. In questo modo, il programmatore ** vede ** cosa deve accadergli, dal momento che deve scriverlo in codice, facendo guadagnare agli sviluppatori molto tempo.

Se ci sono troppi oggetti globali e ci sono troppi parametri nelle funzioni che ne hanno bisogno, puoi sempre raggruppare i tuoi “oggetti globali” in una class, style * factory *, che costruisce e restituisce l’istanza dell’object globale “(simulato) che si desidera, passando la factory come parametro agli oggetti che necessitano l’object globale come dipendenza.

Se si passa alla modalità di test, è sempre ansible creare un factory di test (che restituisce versioni diverse degli stessi oggetti) e passarlo come parametro senza dover modificare la class di destinazione.

Ma è sempre male?

Non necessariamente, ci possono essere buoni usi per le variabili globali. Ad esempio, valori costanti (il valore PI). Essendo un valore costante, non c’è il rischio di non conoscere il suo valore in un dato punto del programma da alcun tipo di modifica da un altro modulo. Inoltre, i valori costanti tendono ad essere primitivi ed è improbabile che cambino la loro definizione.

È più conveniente, in questo caso, utilizzare variabili globali per evitare di dover passare le variabili come parametri, semplificando le firme delle funzioni.

Un altro può essere servizi “globali” non intrusivi, come una class di registrazione (salvataggio di ciò che accade in un file, che di solito è facoltativo e configurabile in un programma, e quindi non influenza il comportamento nucleare dell’applicazione), o std :: cout , std :: cin o std :: cerr , che sono anche oggetti globali.

Qualsiasi altra cosa, anche se la sua vita coincide quasi con quella del programma, passarla sempre come parametro. Anche la variabile potrebbe essere globale in un modulo, solo in essa senza che nessun altro abbia accesso, ma che, in ogni caso, le dipendenze sono sempre presenti come parametri.

Risposta di: Peregring-lk