Как использовать глобальные переменные в 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);
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.