Como usar variáveis ​​globais em C #?


101

Como declaro uma variável para que cada classe (* .cs) possa acessar seu conteúdo, sem uma referência de instância?

Respostas:


123

Em C#você não pode definir variáveis ​​globais verdadeiras (no sentido de que elas não pertencem a nenhuma classe).

Dito isso, a abordagem mais simples que conheço para imitar esse recurso consiste em usar um static class, da seguinte maneira:

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
}

Você pode então recuperar os valores definidos em qualquer lugar em seu código (desde que faça parte do mesmo namespace):

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

Para lidar com diferentes namespaces, você pode:

  • declara a Globalsclasse sem incluí-la em um específico namespace(de forma que seja colocada no namespace do aplicativo global);
  • insira a diretiva using apropriada para recuperar as variáveis ​​de outro namespace.

@Zarathos a classe tem que ser estática também?
Kosnkov

4
Bem, não é necessário, mas não vejo por que você deveria instanciá-lo.
Tommaso Belluzzo

Se você tiver que instanciar sua definição, não mais "global", não faz parte do estado do aplicativo
Viking

Olá, qual seria a diferença se eu não digitasse a palavra-chave estática na classe? Só deixei a string FILE_NAME estática, tentei e ainda funcionou para mim.
Tomer Cahal

1
Sem o atributo estático, sua classe será instanciada (Globals g = new Globals ()). Não altera o comportamento das variáveis ​​estáticas declaradas internamente, mas não parece realmente útil.
Tommaso Belluzzo

74

Não existe variável global em C #. Período.

Você pode ter membros estáticos se quiser:

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

Embora eu concorde, você poderia explicar por que não existe uma variável global em C #? Eu estava tentando pensar em um bom motivo pelo qual aquele mesmo staticexemplo que você forneceu não pode realmente ser considerado uma var global.
cregox de

3
@cawas porque o próprio conceito de uma "variável global" (pendurada do nada, flutuando no limbo, não pertencendo a nenhuma classe) vai contra a própria natureza da OOP. e C # é estritamente orientado a objetos.
Federico Berasategui

Sim, esse é todo o conceito com o qual concordo. Mas, ao tornar esse membro estático, você acabou de criar uma espécie de var global. Como isso difere do var global que você disse que não existe? Eu gostaria de ver um exemplo prático.
cregox de

1
Sinto que você está fugindo da minha pergunta ou não estou claro. Mas eu já respondi. Aqui: stackoverflow.com/a/20010543/274502
cregox

7
Agora percebo o que quero dizer é que os membros estáticos são conceitual e praticamente vars globais (exceto talvez para aquela coisa de heap , que só faz diferença a menos que você esteja escrevendo código inseguro ou fazendo algum tipo de interoperação pesada com código não gerenciado ). Então eu não sei por que alguém diria " não existe algo como variável global em csharp ". Isso me confundiu muito.
cregox de

23

Em primeiro lugar, examine se você realmente precisa de uma variável global, em vez de usá-la descaradamente, sem levar em consideração a arquitetura do software.

Vamos supor que ele passe no teste. Dependendo do uso, Globals pode ser difícil de depurar com condições de corrida e muitas outras "coisas ruins", é melhor abordá-los de um ângulo onde você esteja preparado para lidar com essas coisas ruins. Assim,

  1. Envolva todas essas variáveis ​​globais em uma única staticclasse (para capacidade de gerenciamento).
  2. Possui propriedades em vez de campos (= 'variáveis'). Dessa forma, você tem alguns mecanismos para resolver quaisquer problemas com gravações simultâneas no Globals no futuro.

O esboço básico para tal classe seria:

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

Uso de outras classes (dentro do mesmo namespace)

// Read
bool areWeAlive = Globals.Expired;

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

4

Um recurso útil para isso é using static

Como outros já disseram, você deve criar uma classe para seus globais:

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

Mas você pode importá-lo assim para não escrever mais o nome da classe na frente de suas propriedades estáticas:

using static Globals;
[...]
Console.WriteLine("Pi is " + PI);
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.