Подтвердить что ты не робот

С# - проверка инициализации переменной

Я хочу проверить, инициализирована ли переменная во время выполнения программно. Чтобы причины этого были менее загадочными, см. Следующий неполный код:

string s;

if (someCondition) s = someValue;
if (someOtherCondition) s = someOtherValue;

bool sIsUninitialized = /* assign value correctly */;

if (!sIsUninitialized) Console.WriteLine(s) else throw new Exception("Please initialize s.");

И заполните соответствующий бит.

Одно хакерское решение - инициализировать s со значением по умолчанию:

string s = "zanzibar";

И затем проверьте, не изменилось ли это:

bool sIsUninitialized = s == "zanzibar";

Однако, что, если someValue или someOtherValue тоже будет "Занзибаром"? Тогда у меня есть ошибка. Любой лучший способ?

4b9b3361

Ответ 1

Код даже не компилируется, если компилятор знает, что переменная не была инициализирована.

string s;
if (condition) s = "test";
// compiler error here: use of unassigned local variable 's'
if (s == null) Console.Writeline("uninitialized");

В других случаях вы можете использовать ключевое слово default, если переменная не была инициализирована. Например, в следующем случае:

class X
{ 
    private string s;
    public void Y()
    {
        Console.WriteLine(s == default(string));  // this evaluates to true
    }
}

В документации указано, что значение по умолчанию (T) даст null для ссылочных типов и 0 для типов значений. Так, как указано в комментариях, это действительно так же, как проверка на нуль.


Все это скрывает тот факт, что вы должны действительно инициализировать переменные, null или что-то еще, когда они впервые объявлены.

Ответ 2

С С# 2.0 у вас есть оператор Nullable, который позволяет вам установить начальное значение null для всех типов значений, позволяющее использовать такие вещи, как:

int? x = null;

if (x.HasValue)
{
    Console.WriteLine("Value for x: " + num.Value); 
}

Что дает: "Значение для x: Null".

Ответ 3

Просто назначьте его null по умолчанию, а не строковое значение

Ответ 4

Здесь один из способов:

string s;
if (someCondition) { s = someValue; }
else if (someOtherCondition) { s = someOtherValue; }
else { throw new Exception("Please initialize s."); }

Console.WriteLine(s)

Это может быть предпочтительным для проверки, является ли строка нулевой, потому что возможно someValue - это метод, который иногда может возвращать значение null. Другими словами, возможно, null является законным значением для инициализации строки.

Лично мне нравится это лучше, чем флаг isInitialized. Зачем вводить дополнительную переменную флага, если вам не нужно? Я не думаю, что это более читаемо.

Ответ 5

Вы можете сохранить отдельный флаг, который указывает, что строка была инициализирована:

string s = null;
bool init = false;
if (conditionOne) {
    s = someValueOne;
    init = true;
}
if (conditionTwo) {
    s = someValueTwo;
    init = true;
}
if (!init) {
    ...
}

Это позаботится о ситуациях, когда назначается s, включая случаи, когда ему назначается null, пустая строка или "zanzibar".

Другим решением является создание статической строки для обозначения "неинициализированного" значения и использование Object.ReferenceEquals вместо ==, чтобы проверить, он изменился. Однако переменный подход bool более четко выражает ваше намерение.

Ответ 6

Я выбираю значения инициализации, которые никогда не могут использоваться, типичные значения включают String.Empty, null, -1 и генератор случайных строк в 256 символов.

Ответ 7

В общем случае назначьте значение по умолчанию null или String.Empty. В ситуациях, когда вы не можете использовать эти "пустые" значения, определите константу для представления неинициализированного значения для конкретного приложения:

const string UninitializedString = "zanzibar";

Затем укажите это значение, когда вы хотите инициализировать или проверить для инициализации:

string foo = UnininitializedString;
if (foo == UninitiaizedString) {
  // Do something
}

Помните, что строки являются неизменяемыми константами в С#, поэтому на самом деле существует только один экземпляр UninitializedString (поэтому это сравнение работает).