Неявная и явная типизация с именем С# 6
Одна из самых полезных функций С# 6 - nameof
, которая позволяет программисту эффективно исключить использование магические строки.
В документации, nameof
возвращает строку:
Используется для получения простого (неквалифицированного) имени строки для переменной, типа или члена.
Это работает отлично с явным вводом текста в следующем примере кода:
string magicString = nameof(magicString);
Однако при использовании неявной типизации с ключевым словом var
:
var magicString = nameof(magicString);
компилятор выдает ошибку:
Нельзя использовать локальную переменную magicString до ее объявления
Затем я немного экспериментировал с С# Interactive, доступным в Visual Studio. Опять же, первый пример работал отлично, но на втором примере на этот раз была сделана другая ошибка:
error CS7019: Тип "magicString" не может быть выведен, поскольку его инициализатор прямо или косвенно ссылается на определение.
Выражение nameof
явно возвращает строку, поэтому почему компилятор неявно вводит его при использовании с инициализированной переменной?
Ответы
Ответ 1
Языковая команда почувствовала, что это не стоит сложной спецификации.
Вы можете увидеть обсуждение здесь.
Основная причина такого поведения заключается в том, что spec говорит (§8.5.1) имена, объявленные с помощью var
, не отображаются в заявлении объявления, так как до nameof
не было способа, которым это могло бы быть действительный.
Неявно введенные локальные объявления переменных подчиняются следующим ограничениям:
- ...
- Инициализатор не может ссылаться на объявленную переменную
Без var
утверждения, подобные int x = x = 1;
или int x = 1, y = x;
, являются законными; с var
, ничего в этой форме не будет.
Ответ 2
Возможность объявлять переменную и назначать ее в одном и том же выражении является синтаксическим сахаром. Например, когда вы это говорите:
string magicString = nameof(magicString);
что вы на самом деле говорите:
string magicString;
magicString = nameof(magicString);
Поскольку magicString
уже объявлен, вы можете использовать его в следующем логическом выражении как часть оператора naemof
. Это связано с тем, что magicString
теперь входит в область , которая видима для последующих операторов.
Теперь приведенное выше не выполняется, когда вы используете var
, потому что все, что использует var
для выполнения задания, действительно является частью всего одного заявления, а не синтаксического сахара для двух операторов, подобных приведенному выше примеру. Переменная magicString
фактически не объявляется до тех пор, пока не будет вызвана функция/оператор/назначение функции, поэтому переменная не является частью области, пока она не выполнила назначение, то есть в следующем утверждении (ы).
SLaks ссылался на оригинальное обсуждение этой проблемы, но в отмечены примечания из этого более позднего дизайна С# собрание команды об этой проблеме по вопросу "Должен ли var x = nameof (x) работать?":
Это работает так же, как и с любой другой конструкцией, т.е. нет. Это а не особый случай для имени, и, похоже, не стоит особого чтобы обеспечить его.
Другими словами, это не относится к nameof
.