Почему "@" разрешено перед любой переменной-членом (т.е. Вызывает функцию/свойство), когда она не влияет на ее значение?

Я знаю, что ключевое слово '@' используется для разных целей в С#, как обсуждалось здесь, но мой вопрос отличается.

Предположим, что вместо ConfigurationManager.AppSetting["DbConnectionString"] я использую @ConfigurationManager.AppSetting["DbConnectionString"]. Он по-прежнему работает таким же образом.

Итак, мои вопросы:

  • Почему символ "@" разрешен компилятором здесь, когда он не влияет на его значение?
  • Может ли символ "@" изменять значения в любом сценарии, как указано выше?

Чтобы сделать его более понятным, я хочу добавить еще один пример:

Предположим, у меня есть класс 'ConfigurationLoader', который имеет статическую функцию 'GetConfigurations' возвращает список строк.

Тогда я могу назвать его List<string> ConnectionStrs=ConfigurationLoader.GetConfigurations();.

Если я делаю это как List<string> [email protected]();, то он все равно дает тот же результат. В таком сенарио я задаю два вопроса.

Ответ 1

UPDATE: этот вопрос был тема моего блога в сентябре 2013 года. Спасибо за отличный вопрос!


Может ли символ "@" изменять значения в любом сценарии, как указано выше?

Нет.

Какую функцию мы говорим?

В С#, если вы предикаете какой-либо идентификатор с @, тогда идентификатор разрешен, но не обязательно, чтобы быть ключевым словом. Эта функция позволила разработчикам использовать зарезервированные ключевые слова в качестве идентификаторов:

static void M(bool @unsafe) { ... }

и это позволяет подчеркнуть, что идентификатор, который может быть путать с контекстуальным ключевым словом, действительно является идентификатором:

@yield = 123.45;

Это было бы законно без @, но ясно, что разработчик не имел в виду yield return 123.45; здесь.

Так почему же тогда это разрешено для идентификаторов, которые не являются ключевыми словами?

Перейдите в машину с возвратом и вернитесь в мир С# 2.0. Предположим, что функция была такой, какой вы предлагаете: @ может содержать только зарезервированные и контекстные ключевые слова. Вы пишете эту программу в С# 2.0:

class P
{
  static void Main()
  {
    int @yield = 123;
  }
}

Не кажется ли немного странным, что это законная программа С# 2.0, но не законная программа С# 1.0, несмотря на отсутствие функций С# 2.0?

Разработанная функция позволяет использовать код между двумя командами, использующими разные версии С#. И это позволяет вам заставить одного человека в команде попробовать С# 2.0, чтобы увидеть, работает ли он, пока все еще используют С# 1.0. Ваша предлагаемая функция делает оба этих сценария кошмарными и создает барьер для принятия новых версий языка. Обновление уже достаточно дорого; команда разработчиков языка не хочет сделать ее еще более дорогой.

Функция, разработанная, также позволяет "будущую проверку". Предположим, вы пишете программу, которая генерирует другие программы. Вы могли бы также сделать сгенерированную программу предисловией всех своих идентификаторов с @, потому что вы не знаете, какие слова станут ключевыми словами в будущих версиях С#.

Где я могу узнать больше о правилах ключевого слова С#?

http://ericlippert.com/2009/05/11/reserved-and-contextual-keywords/

Ответ 2

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

1. Почему символ "@" разрешен компилятором здесь, когда он не влияет на его значение?

Потому что это говорит спецификация языка. Символ @перед токеном не означает "Следующий токен - это ключевое слово, но относиться к нему как к идентификатору". Это не то, как написана спецификация, так что не так, как работает компилятор языка. Скорее, это означает "независимо от следующего токена, относитесь к нему как к идентификатору, даже если это ключевое слово".

Это то же самое, что сказать, например, "притвориться синим цветом". Это легко сделать, потому что синий цвет. Похоже, что "притворяться myCollection не является ключевым словом С#", это просто - это не ключевое слово С#, поэтому ничего не делать.

То, что вы действительно пытаетесь спросить, я подозреваю, это:

1b. Почему люди, которые разработали С#, определяют поведение символа @ таким образом?

Этот вопрос, боюсь, может ответить только тот, кто помог определить С#. Мы можем догадаться, и ответ почти наверняка будет состоять в том, что уже несколько человек уже прокомментировали: потому что этот способ был проще (объяснить, документировать, реализовать, протестировать и т.д.) И не имел недостатков. Ну, кроме некоторой легкой путаницы со стороны некоторых разработчиков.:)

Добавление требования в спецификацию, что компилятор делает что-то при "злоупотреблении" символом @, означает большую работу. Вы должны определить, что он делает (это предупреждение? Ошибка?), Вы должны добавить правильный, точный, корректурный, однозначный язык для спецификации, вам нужно добавить код в компилятор для создания нового поведения, вы должны документируйте новое поведение, вы должны написать тестовые скрипты для осуществления нового поведения и т.д. Все для "функции", которая имеет нулевое добавленное преимущество.

Это делает использование @избыточным, но С# позволяет вам делать много избыточных вещей по разным причинам. Вы можете добавить избыточный (), вы можете добавить избыточные конструкторы делегатов, вы можете добавить избыточные ключевые слова доступности. И, как вы можете видеть, вы можете добавить избыточный @ по всему месту, если хотите.

2. Может ли символ "@" изменять значения в любом сценарии, как указано выше?

В этом случае мы можем ответить: Нет. Если вы поместите @ перед токеном, который уже является идентификатором, он будет рассматриваться как идентификатор - тот же самый идентификатор, который компилятор собирался ссылаться в любом случае. Вы не увидите изменений в поведении, это просто добавление текста.

Ответ 3

Вопрос, на который вы ссылаетесь, отвечает на ваш вопрос. В этом контексте @ сообщает компилятору, что следующий символ является идентификатором, без ключевого слова. Это вам не нужно для ConfigurationManager, но его все равно можно использовать. Вот пример того, где это потребуется:

class @class
{
    public @class()
    {
    }
}

class Program
{
    static void Main(string[] args)
    {
        @class c = new @class();
    }
}

Ответ 4

Вы можете использовать символ @ для использования зарезервированных ключевых слов в качестве простых имен переменных, например:

int @for = 10;

Console.WriteLine(@for); // 10

Точно так же вы можете иметь переменную с именем @hello вместо hello, хотя hello не является зарезервированным ключевым словом, для которого требуется префикс @, чтобы использовать его как имя переменной.

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

Две возможные причины:

  • Предполагалось, что @ разрешен только по зарезервированным ключевым словам (и экранирующим строкам), но кто-то забыл if, а другим это было неважно.
  • Предполагалось, что @ разрешено использовать зарезервированные ключевые слова, и в первую очередь никто не заботится о том, будет ли он использоваться и другими способами.