C # – Formas de pago – Variables globales

Quiero que algunas variables sean globales en todo el proyecto y accesibles en todas sus formas. ¿Cómo puedo hacer esto?

sí puedes usando clase estática. Me gusta esto:

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

y para usar cualquier lugar donde puedas escribir:

 GlobalClass.GlobalVar = "any string value" 

O podrías poner tus globales en la app.config

Puede usar una clase estática o un patrón Singleton .

De una sola mano,

Solution Explorer> Your Project> Properties> Settings.Settings. Haga clic en este archivo y agregue definir su configuración desde el IDE.

Acceda a ellos por

 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 } } 

El consenso aquí es poner las variables globales en una clase estática como miembros estáticos. Cuando crea una nueva aplicación de Windows Forms, generalmente viene con una clase Program (Program.cs), que es una clase estática y sirve como el punto de entrada principal de la aplicación. Vive durante toda la vida de la aplicación, por lo que creo que es mejor colocar las variables globales en lugar de crear una nueva.

 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()); } } 

Y úsalo como tal:

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

Si está usando Visual C #, todo lo que necesita hacer es agregar una clase en Program.cs heredando Form y cambiando toda la clase heredada de Form a su clase en cada 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 { //... } 

Por supuesto, puede haber una forma de extender el formulario de clase sin modificarlo . Si ese es el caso, ¡todo lo que necesita hacer es extenderlo! Dado que todos los formularios lo están heredando de forma predeterminada, ¡todos los objetos de valor declarados se convertirán en globales automáticamente! ¡¡¡Buena suerte!!!

Ya han respondido cómo usar una variable global.

Te diré por qué el uso de variables globales es una mala idea como resultado de esta pregunta realizada en stackoverflow en español.

Traducción explícita del texto en español:

Impacto del cambio

El problema con las variables globales es que crean dependencias ocultas. Cuando se trata de aplicaciones grandes, usted mismo no sabe / recuerda / tiene claros los objetos que tiene y sus relaciones.

Por lo tanto, no puede tener una noción clara de cuántos objetos está usando su variable global. Y si quiere cambiar algo de la variable global, por ejemplo, ¿el significado de cada uno de sus valores posibles, o su tipo? ¿Cuántas clases o unidades de comstackción cambiará? Si la cantidad es pequeña, puede valer la pena realizar el cambio. Si el impacto será grande, puede valer la pena buscar otra solución.

Pero, ¿cuál es el impacto? Debido a que una variable global se puede usar en cualquier parte del código, puede ser muy difícil medirla.

Además, siempre trate de tener una variable con el tiempo de vida más corto posible, de modo que la cantidad de código que hace uso de esa variable sea la mínima posible, y así comprenda mejor su propósito, y quién lo modifique.

Una variable global dura por la duración del progtwig, y ​​por lo tanto, cualquiera puede usar la variable, ya sea para leerla, o incluso peor, para cambiar su valor, lo que hace más difícil saber qué valor tendrá la variable en cualquier progtwig dado. punto. .

Orden de destrucción

Otro problema es el orden de la destrucción. Las variables siempre se destruyen en el orden inverso de su creación, ya sean variables locales o globales / estáticas (una excepción son los tipos primitivos, int , enum s, etc., que nunca se destruyen si son globales / estáticos hasta que terminan el progtwig).

El problema es que es difícil conocer el orden de construcción de las variables globales (o estáticas). En principio, es indeterminado.

Si todas sus variables globales / estáticas están en una sola unidad de comstackción (es decir, usted solo tiene un .cpp ), entonces el orden de construcción es el mismo que el de escritura (es decir, las variables definidas anteriormente, se construyen antes).

Pero si tiene más de un .cpp cada uno con sus propias variables globales / estáticas, el orden de construcción global es indeterminado. Por supuesto, se respeta el orden en cada unidad de comstackción (cada .cpp ) en particular: si la variable global A se define antes que B , A se construirá antes que B , pero es posible que entre las variables A y B de otra .cpp están inicializados. Por ejemplo, si tiene tres unidades con las siguientes variables globales / estáticas:

Imagen1

En el ejecutable, podría crearse en este orden (o en cualquier otro orden, siempre que se respete el orden relativo dentro de cada .cpp ):

Imagen2

¿Porque es esto importante? Porque si hay relaciones entre diferentes objetos globales estáticos, por ejemplo, que algunos utilizan otros en sus destructores, quizás, en el destructor de una variable global, utilice otro objeto global de otra unidad de comstackción que resulte ya destruida (tenga construido más tarde).

Dependencias ocultas y * casos de prueba *

Intenté encontrar la fuente que usaré en este ejemplo, pero no puedo encontrarla (de todos modos, fue para ejemplificar el uso de singletons, aunque el ejemplo es aplicable a variables globales y estáticas). Las dependencias ocultas también crean nuevos problemas relacionados con el control del comportamiento de un objeto, si depende del estado de una variable global.

Imagine que tiene un sistema de pago y desea probarlo para ver cómo funciona, ya que necesita hacer cambios, y el código es de otra persona (o la suya, pero desde hace algunos años). Abre una nueva línea main y llama a la función correspondiente de su objeto global que proporciona una tarjeta con un servicio de pago bancario, y resulta que ingresa sus datos y le cobran. ¿Cómo, en una prueba simple, utilicé una versión de producción? ¿Cómo puedo hacer una simple prueba de pago?

Después de preguntar a otros compañeros de trabajo, resulta que debe marcar “verdadero”, un bool global que indica si estamos en modo prueba o no, antes de comenzar el proceso de recostackción. Su objeto que proporciona el servicio de pago depende de otro objeto que proporciona el modo de pago, y esa dependencia se produce de forma invisible para el progtwigdor.

En otras palabras, las variables globales (o singletones) hacen imposible pasar al “modo de prueba”, ya que las variables globales no pueden ser reemplazadas por instancias de “prueba” (a menos que modifiques el código donde se crea o define dicho código). variable global, pero suponemos que las pruebas se realizan sin modificar el código madre).

Solución

Esto se resuelve mediante lo que se llama * dependency injection *, que consiste en pasar como parámetro todas las dependencias que un objeto necesita en su constructor o en el método correspondiente. De esta forma, el progtwigdor ** ve ** lo que le debe suceder, ya que tiene que escribirlo en código, lo que hace que los desarrolladores ganen mucho tiempo.

Si hay demasiados objetos globales, y hay demasiados parámetros en las funciones que los necesitan, siempre puede agrupar sus “objetos globales” en una clase, style * factory *, que construye y devuelve la instancia del “objeto global” “(simulado) que desee, pasando la fábrica como parámetro a los objetos que necesitan el objeto global como dependencia.

Si pasa al modo de prueba, siempre puede crear una fábrica de pruebas (que devuelve diferentes versiones de los mismos objetos) y pasarla como parámetro sin tener que modificar la clase objective.

Pero, ¿siempre es malo?

No necesariamente, puede haber buenos usos para las variables globales. Por ejemplo, valores constantes (el valor de PI). Siendo un valor constante, no hay riesgo de no conocer su valor en un punto dado del progtwig por cualquier tipo de modificación de otro módulo. Además, los valores constantes tienden a ser primitivos y es poco probable que cambien su definición.

En este caso, es más conveniente utilizar variables globales para evitar tener que pasar las variables como parámetros, simplificando las firmas de las funciones.

Otro puede ser servicios “globales” no intrusivos, como una clase de registro (guardando lo que sucede en un archivo, que generalmente es opcional y configurable en un progtwig, y ​​por lo tanto no afecta el comportamiento nuclear de la aplicación), o std :: cout , std :: cin o std :: cerr , que también son objetos globales.

Cualquier otra cosa, incluso si su tiempo de vida coincide casi con el del progtwig, siempre se pasa como un parámetro. Incluso la variable podría ser global en un módulo, solo que sin ningún otro acceso, pero que, en cualquier caso, las dependencias siempre están presentes como parámetros.

Respuesta de: Peregring-lk