web-dev-qa-db-fra.com

C # - Winforms - Variables globales

Je veux que certaines variables soient globales à travers le projet et accessibles sous toutes les formes. Comment puis-je faire ceci?

27
Moon

oui vous pouvez en utilisant la classe statique. comme ça:

static class Global
{
    private static string _globalVar = "";

    public static string GlobalVar
    {
        get { return _globalVar; }
        set { _globalVar = value; }
    }
}

et pour utiliser n'importe où vous pouvez écrire:

GlobalClass.GlobalVar = "any string value"
76
Wael Dalloul

Ou vous pouvez mettre vos globaux dans app.config

6
Rigobert Song

Vous pouvez utiliser classe statique ou modèle Singleton .

5
Michał Ziober

Une manière,

Explorateur de solutions> Votre projet> Propriétés> Paramètres. Paramètres. Cliquez sur ce fichier et ajoutez définir vos paramètres depuis l'IDE.

Accédez-y par

Properties.Settings.Default.MySetting = "hello world";
4
Steve

Le consensus ici est de mettre les variables globales dans une classe statique en tant que membres statiques. Lorsque vous créez une nouvelle application Windows Forms, elle est généralement fournie avec une classe Program (Program.cs), qui est une classe statique et sert de point d'entrée principal de l'application. Il vit pendant toute la durée de vie de l'application, donc je pense qu'il est préférable d'y placer les variables globales au lieu d'en créer une nouvelle.

static class Program
{
    public static string globalString = "This is a global string.";

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
}

Et utilisez-le comme tel:

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

        InitializeComponent();
    }
}
4
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
    }
}
2
user138894

Ils ont déjà expliqué comment utiliser une variable globale.

Je vais vous dire pourquoi l'utilisation de variables globales est une mauvaise idée à cause de cela question effectuée en stackoverflow en espagnol.

Traduction explicite du texte en espagnol:

Impact du changement

Le problème avec les variables globales est qu'elles créent des dépendances cachées. En ce qui concerne les grandes applications, vous ne savez pas/ne vous souvenez pas/vous êtes clair sur les objets que vous avez et leurs relations.

Ainsi, vous ne pouvez pas avoir une idée claire du nombre d'objets que votre variable globale utilise. Et si vous voulez changer quelque chose de la variable globale, par exemple, la signification de chacune de ses valeurs possibles, ou son type? Combien de classes ou d'unités de compilation ce changement affectera-t-il? Si le montant est petit, il peut être utile de faire le changement. Si l'impact est important, il peut être utile de rechercher une autre solution.

Mais quel est l'impact? Puisqu'une variable globale peut être utilisée n'importe où dans le code, il peut être très difficile de la mesurer.

De plus, essayez toujours d'avoir une variable avec la durée de vie la plus courte possible, afin que la quantité de code qui utilise cette variable soit le minimum possible, et ainsi mieux comprendre son objectif, et qui la modifie.

Une variable globale dure pendant la durée du programme, et donc, n'importe qui peut utiliser la variable, soit pour la lire, ou pire encore, pour changer sa valeur, ce qui rend plus difficile de savoir quelle valeur la variable aura à un programme donné point. .

Ordre de destruction

Un autre problème est l'ordre de destruction. Les variables sont toujours détruites dans l'ordre inverse de leur création, qu'il s'agisse de variables locales ou globales/statiques (une exception est les types primitifs, int, enum s, etc., qui ne sont jamais détruits) s'ils sont globaux/statiques jusqu'à la fin du programme).

Le problème est qu'il est difficile de connaître l'ordre de construction des variables globales (ou statiques). En principe, il est indéterminé.

Si toutes vos variables globales/statiques sont dans une seule unité de compilation (c'est-à-dire que vous n'avez qu'un .cpp), alors l'ordre de construction est le même que celui d'écriture (c'est-à-dire que les variables définies avant, sont construites avant).

Mais si vous en avez plusieurs .cpp chacun avec ses propres variables globales/statiques, l'ordre de construction global est indéterminé. Bien sûr, l'ordre dans chaque unité de compilation (chaque .cpp) en particulier, est respecté: si la variable globale A est définie avant B, A sera construite avant B, mais c'est possible entre A et B variables d'autres .cpp sont initialisés. Par exemple, si vous avez trois unités avec les variables globales/statiques suivantes:

Image1

Dans l'exécutable, il pourrait être créé dans cet ordre (ou dans tout autre ordre tant que l'ordre relatif est respecté dans chaque .cpp):

Image2

Pourquoi est-ce important? Parce que s'il existe des relations entre différents objets globaux statiques, par exemple, que certains utilisent d'autres dans leurs destructeurs, peut-être dans le destructeur d'une variable globale, vous utilisez un autre objet global d'une autre unité de compilation qui s'avère déjà détruit (avoir été construit plus tard).

Dépendances cachées et * cas de test *

J'ai essayé de trouver la source que j'utiliserai dans cet exemple, mais je ne la trouve pas (de toute façon, c'était pour illustrer l'utilisation de singletons, bien que l'exemple soit applicable aux variables globales et statiques). Les dépendances cachées créent également de nouveaux problèmes liés au contrôle du comportement d'un objet, s'il dépend de l'état d'une variable globale.

Imaginez que vous avez un système de paiement et que vous souhaitez le tester pour voir comment il fonctionne, car vous devez apporter des modifications et le code provient d'une autre personne (ou de la vôtre, mais il y a quelques années). Vous ouvrez un nouveau main, et vous appelez la fonction correspondante de votre objet global qui fournit un service de paiement bancaire avec une carte, et il s'avère que vous entrez vos données et ils vous facturent. Comment, dans un test simple, ai-je utilisé une version de production? Comment faire un simple test de paiement?

Après avoir demandé à d'autres collègues, il s'avère que vous devez "marquer vrai", un bool global qui indique si nous sommes en mode test ou non, avant de commencer le processus de collecte. Votre objet qui fournit le service de paiement dépend d'un autre objet qui fournit le mode de paiement, et cette dépendance se produit de manière invisible pour le programmeur.

En d'autres termes, les variables globales (ou singletones), rendent impossible le passage en "mode test", car les variables globales ne peuvent pas être remplacées par des instances "testing" (sauf si vous modifiez le code où ce code est créé ou défini). variable globale, mais nous supposons que les tests sont effectués sans modifier le code mère).

Solution

Ceci est résolu au moyen de ce qu'on appelle * l'injection de dépendances *, qui consiste à passer en paramètre toutes les dépendances dont un objet a besoin dans son constructeur ou dans la méthode correspondante. De cette façon, le programmeur ** voit ** ce qui doit lui arriver, car il doit l'écrire dans le code, ce qui fait gagner beaucoup de temps aux développeurs.

S'il y a trop d'objets globaux et qu'il y a trop de paramètres dans les fonctions qui en ont besoin, vous pouvez toujours grouper vos "objets globaux" dans une classe, style * factory *, qui construit et renvoie l'instance de "l'objet global" "(simulé) que vous souhaitez, en passant la fabrique comme paramètre aux objets qui ont besoin de l'objet global comme dépendance.

Si vous passez en mode test, vous pouvez toujours créer une fabrique de tests (qui renvoie différentes versions des mêmes objets) et la passer en paramètre sans avoir à modifier la classe cible.

Mais est-ce toujours mauvais?

Pas nécessairement, il peut y avoir de bonnes utilisations pour les variables globales. Par exemple, des valeurs constantes (la valeur PI). Etant une valeur constante, il n'y a aucun risque de ne pas connaître sa valeur à un point donné du programme par tout type de modification d'un autre module. De plus, les valeurs constantes ont tendance à être primitives et ne changeront probablement pas leur définition.

Il est plus pratique, dans ce cas, d'utiliser des variables globales pour éviter d'avoir à passer les variables en paramètres, simplifiant ainsi les signatures des fonctions.

Un autre peut être des services "globaux" non intrusifs, comme une classe de journalisation (enregistrer ce qui se passe dans un fichier, qui est généralement facultatif et configurable dans un programme, et par conséquent n'affecte pas le comportement nucléaire de l'application), ou std :: cout, std :: cin ou std :: cerr, qui sont également des objets globaux.

Toute autre chose, même si sa durée de vie coïncide presque avec celle du programme, la transmet toujours en paramètre. Même la variable pourrait être globale dans un module, seulement dedans sans qu'aucun autre n'y ait accès, mais qu'en tout cas, les dépendances sont toujours présentes comme paramètres.

Réponse par: Peregring-lk

1
J. Rodríguez

Si vous utilisez Visual C #, il vous suffit d'ajouter une classe dans Program.cs héritant de Form et de changer toute la classe héritée de Form en votre classe dans chaque 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
{
    //...
}

Bien sûr, il pourrait y avoir un moyen d'étendre le formulaire Form sans le modifier . Si tel est le cas, il vous suffit de l'étendre! Étant donné que tous les formulaires en héritent par défaut, tous les objets de valeur qui y sont déclarés deviendront automatiquement globaux! Bonne chance!!!

0
user8931966