Использование переменной в качестве аргумента out в точке объявления

При чтении comment в ответ я увидел следующую конструкцию для объявления и инициализации переменной:

int variable = int.TryParse(stringValue, out variable) ? variable : 0;

Это разрешено, правильно и четко определено в С#? Что происходит под капотом? Что происходит?

  • Изначально variable инициализируется до нуля?
  • затем передается в int.TryParse (который присваивает значение)?
  • затем, возможно, прочитайте (если int.TryParse return true)?
  • а затем, снова назначенный/инициализированный?

Ответы

Ответ 1

Это трюк, который срабатывает, потому что это просто переписывание обычного оператора if. Этот код эквивалентен этому:

int variable;
if (int.TryParse(stringVariable, out variable))
    variable = variable;
else
    variable = 0;

Последовательность выглядит следующим образом:

int.TryParse, variable не инициализируется до этого, но ему также не нужно. Параметр out не требует определенной назначенной переменной. Как часть выполнения метода, variable получит значение, а int.TryParse вернет true или false.

Если метод возвращает true, тогда результат выражения будет variable и, следовательно, мы будем выполнять в основном variable = variable.

Если метод возвращает false, тогда результат выражения будет 0, а variable теперь будет иметь значение 0, независимо от того, что оно было дано как часть int.TryParse. В этом случае, однако, это не изменит переменную, поскольку int.TryParse уже присвоило variable значение по умолчанию, когда оно возвращает false, которое также оказывается 0.

Это в основном способ получить все на одной строке.

Лично я бы написал этот код следующим образом:

int variable;
int.TryParse(stringValue, out variable);

Ответ 2

Да, вы правы для исполнения. Вы также можете посмотреть здесь созданные MSIL.

Код С#

 string stringValue = "5";
 int variable = int.TryParse(stringValue, out variable) ? variable : 0;

Созданный MSIL

1.  IL_0000:  nop    
2.  IL_0001:  ldstr      "5" // load string
3.  IL_0006:  stloc.0
4.  IL_0007:  ldloc.0
5.  IL_0008:  ldloca.s   variable
6.  IL_000a:  call       bool [mscorlib]System.Int32::TryParse(string, int32&)
7.  IL_000f:  brtrue.s   IL_0014
8.  IL_0011:  ldc.i4.0
9.  IL_0012:  br.s       IL_0015
10. IL_0014:  ldloc.1
11. IL_0015:  stloc.1
12. IL_0016:  ret

Что разъясняет, что он делает за сценой.

Ведомость 5 выделяет переменную в стек. Вызов 6 вызывает метод. Заявление 7,8,9 фактически exeuting выражение bool.

Ответ 3

int variable объявляет variable, а out variable обязательно инициализирует его. Обе эти вещи должны произойти до того, как variable используется где угодно, и из-за объявления out это верно.

Как указал Лассе В. Карлсен, из документации TryParse, TryParse по умолчанию назначит ему значение 0, если преобразование не выполняется:

Когда этот метод возвращается, [ return] содержит 32-разрядное знаковое целочисленное значение, эквивалентное числу, содержащемуся в s, если преобразование выполнено успешно, или ноль, если преобразование завершилось с ошибкой. (emph мой)

Если вы выберете тройную функцию, вы увидите:

int variable;
if (int.TryParse(stringValue, out variable))
    variable = variable;
else
    variable = 0;

который сам по себе является юридическим выражением. Два пути:

  • TryParse присваивает значение variable и возвращает true, что приводит к присваиванию variable самому себе
  • TryParse инициализирует variable до 0 и возвращает false, что приводит к присваиванию variable как нуля по тернарному условию

Это не совсем четкий код, и я бы не рекомендовал его делать.

Ответ 4

Я не открыл Visual Studio, чтобы попробовать, но да, это разрешено.

Все зависит от переменной "stringValue". Если это можно разделить на целое число, int.TryParse вернет true, а [variable] будет иметь целочисленное значение. Если нет, то variable будет установлено в 0.

Это делает для читаемого кода? Видимо, нет.