Как использовать глобальные переменные в C #?

101

Как объявить переменную, чтобы каждый класс (* .cs) мог получить доступ к ее содержимому без ссылки на экземпляр?

Мас Аджум
источник

Ответы:

124

В нем C#нельзя определить истинные глобальные переменные (в том смысле, что они не принадлежат ни к какому классу).

При этом самый простой подход, который я знаю для имитации этой функции, состоит в использовании static classследующего:

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
}

Затем вы можете получить определенные значения в любом месте вашего кода (при условии, что они являются его частью namespace):

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

Чтобы иметь дело с разными пространствами имен, вы можете:

  • объявить Globalsкласс, не включая его в конкретный namespace(чтобы он был помещен в глобальное пространство имен приложения);
  • вставьте соответствующую директиву using для извлечения переменных из другого namespace.
Томмазо Беллуццо
источник
@Zarathos, класс тоже должен быть статическим?
kosnkov
4
Ну, в этом нет необходимости, но я не понимаю, зачем вам создавать его экземпляр.
Tommaso Belluzzo
Если вам нужно создать его экземпляр по определению, который больше не является «глобальным» и не является частью состояния приложения
Viking
Привет, какая была бы разница, если бы я не вводил ключевое слово static в классе? Я только сделал строку FILE_NAME статической, я попробовал, но у меня все еще работало.
Томер Кахал,
1
Без атрибута static ваш класс будет инстанцируемым (Globals g = new Globals ()). Это не меняет поведения статических переменных, объявленных внутри, но не выглядит действительно полезным.
Томмазо Беллуццо
74

В C # нет такой вещи, как глобальная переменная. Период.

Вы можете иметь статические члены, если хотите:

public static class MyStaticValues
{
   public static bool MyStaticBool {get;set;}
}
Федерико Берасатеги
источник
Хотя я согласен, не могли бы вы рассказать подробнее, почему в C # нет такой вещи, как глобальная переменная? Я пытался придумать вескую причину, по которой тот самый staticпример, который вы предоставили, на самом деле нельзя рассматривать как глобальную переменную.
cregox
3
@cawas, потому что сама концепция «глобальной переменной» (свисающая из ниоткуда, плавающая в подвешенном состоянии, не принадлежащая какому-либо классу) противоречит самой природе ООП. а C # строго объектно-ориентирован.
Федерико Берасатеги
Да, это все, с чем я согласен. Но сделав этот статический член, вы просто создали своего рода глобальную переменную. Чем это отличается от глобального var, которого, по вашему мнению, не существует? Хочу увидеть практический пример.
cregox
1
Я чувствую, что вы либо уклоняетесь от моего вопроса, либо я не понимаю. Но я уже получил ответ. Здесь: stackoverflow.com/a/20010543/274502
cregox
7
Теперь я понимаю, что я имел в виду, что статические члены концептуально и практически являются глобальными переменными (за исключением, может быть, этой кучи , которая имеет значение, только если вы не пишете небезопасный код или не выполняете какое-то тяжелое взаимодействие с неуправляемым кодом ). Так что я не знаю, почему кто-то сказал: « В csharp нет такой вещи, как глобальная переменная ». Это меня сильно смутило.
cregox
23

Сначала проверьте, действительно ли вам нужна глобальная переменная, вместо того, чтобы использовать ее явно, без учета архитектуры вашего программного обеспечения.

Предположим, он прошел тест. В зависимости от использования Globals может быть трудно отлаживать из-за условий гонки и многих других «плохих вещей», лучше всего подходить к ним с той точки зрения, с которой вы готовы справиться с такими плохими вещами. Так,

  1. Оберните все такие глобальные переменные в один staticкласс (для удобства управления).
  2. Имейте свойства вместо полей (= 'переменные'). Таким образом, у вас есть механизмы для решения любых проблем с одновременной записью в Globals в будущем.

Базовая схема такого класса:

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

Использование из других классов (в том же пространстве имен)

// Read
bool areWeAlive = Globals.Expired;

// Write
// past deadline
Globals.Expired = true;
Сид
источник
4

Для этого полезной функцией является using static

Как говорили другие, вам нужно создать класс для своих глобальных объектов:

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

Но вы можете импортировать его так, чтобы больше не писать имя класса перед его статическими свойствами:

using static Globals;
[...]
Console.WriteLine("Pi is " + PI);
Zotta
источник