Почему я могу создать класс с именем «var»?


103

Разве это не varключевое слово в C #? Но почему я могу это сделать:

public class var { }

public class main
{
    public static void main(string[] args)
    {
        var testVar = new var();
    }
}

В varкоде используется varкласс, объявленный перед mainклассом. А компилятор даже не жалуется.

А когда я это делаю:

public class int { }

или это:

public class true { }

Компилятор сказал, что intили trueявляется ключевым словом и не может использоваться таким образом. Почему не то же самое с var?


6
Зачем тебе это нужно? Так запутанно и трудно читать.
— duffymo


31
var'y хороший вопрос!
— Ричард

50
Вы также можете сделать это var var = "var";в методе. В конце концов, сегодня пятница.
— Хенк Холтерман

11
Я предполагаю, что они сделали это таким образом, чтобы обеспечить обратную совместимость с кодом create до того, как "var" означало что-то особенное.
— vidstige

Ответы:


101

varне является ключевым словом согласно этому списку .

это контекстное ключевое слово, поэтому из контекста компилятор может решить, какой класс является вашим, а какой - контекстным, и не возникнет путаницы.

контекстное ключевое слово:

используется для придания определенного значения в коде, но это не зарезервированное слово в C #.

так как он не зарезервирован, вы можете его использовать.

Как указано в комментариях выше, есть обсуждение различий, а также список различных ключевых слов и контекстных ключевых слов, добавленных в каждой версии c # в блоге Эрика Липпертса.

Интересно отметить, что, поскольку набор ключевых слов был определен в C # 1.0, не было никаких добавлений, чтобы сохранить обратную совместимость.


1
Однако здесь он отнесен к категории «Ключевые слова C #» msdn.microsoft.com/en-us/library/bb383973.aspx ... сбивает с толку!
— Ричард

4
Но это Contextual Keyword. «Контекстное ключевое слово используется для придания определенного значения в коде, но это не зарезервированное слово в C # . Некоторые контекстные ключевые слова, такие как partial и where, имеют особые значения в двух или более контекстах».
— Тим Шмелтер

5
@TimSchmelter Тогда «var» - это «ключевое слово». Просто не зарезервированное слово, правда?
— luiscubal

2
Я предполагаю, что это для поддержания совместимости со старым кодом - если у кого-то был класс с именем, varтогда не все ломается при обновлении C #.
— Каллум Роджерс

1
@CallumRogers: именно поэтому команда C # сделала это. То же самое для других введенных позже "ключевых слов", таких как from, join и т.д. (кстати, все контекстные).
— Авель

18

Компилятор достаточно умен, чтобы знать, что контекст, который вы используете varв качестве имени класса, никогда не является контекстом для ключевого слова, поэтому позволяет это (вот почему оно определяется как контекстное ключевое слово ).


Я думаю, что этот ответ, по крайней мере, несколько вводит в заблуждение. Компилятор не совсем «умен», чтобы определить, varиспользуется ли в качестве ключевого слова в коде, например var testVar = new var();. Да, контекст, с точки зрения того, был ли определен пользовательский тип с именем var, играет в него, но именно потому, что компилятор недостаточно умен в этих случаях, чтобы знать, var testVarотносится ли он к классу varили к ключевому слову, varкоторое он по умолчанию относится к классу в таком контексте. Если бы varключевое слово было названо по-другому, его можно было бы использовать в том же «контексте».
— OR Mapper

Сравните это с другими контекстными ключевыми словами, такими как add- здесь, компилятор действительно в каждом случае знает, имеется в виду ключевое слово (объявление события; идентификатор не имеет никакого смысла) или ссылается ли код на идентификатор (тип или name в объявлении, использование идентификатора в теле метода; ключевое слово там не имело бы никакого смысла).
— OR Mapper

12

Другой способ взглянуть на это: «var» как ключевое слово не было в первых версиях C # (в отличие от «int» и «true»), поэтому вы могли написать код, который имел бы класс с именем «var». Это было прекрасно и законно. Позже, когда "var" был добавлен в язык, дизайнеры были настолько любезны, что сделали его ключевым словом только в определенных контекстах, чтобы ваш существующий класс var продолжал работать.

Это одна из реальных проблем языкового дизайна - как добавлять новые функции, не нарушая существующий код и не делая новые функции громоздкими в использовании.


8

В версиях C # до версии 3 неявно типизированные локальные переменные еще не поддерживались, поэтому varне имели особого значения, и можно было определять переменные и классы с именами var. Ваш пример программы является законным, потому что оба вхождения varin mainотносятся к классу var.

C # 3 и более поздние версии имеют обратную совместимость, поэтому код, написанный на C # до версии 3, по-прежнему компилируется с новыми компиляторами.

intи trueявляются ключевыми словами, начиная с C # 1.


3

Ключевые слова можно зарезервировать контекстно. Когда исходный код анализируется, этот контекст устанавливается как часть дерева синтаксического анализа. Оценка ключевых слов происходит в этом контексте. Итак, в этом случае var не находится в зарезервированном контексте и не будет иметь того же значения, что и когда вы используете его в операторе присваивания. Я считаю, что одна из причин такой гибкости заключается в том, что var был введен в C # 3, поэтому его резервирование повсюду могло нарушить обратную совместимость в некоторых программах, тогда как использование его в качестве объявления типа переменной не могло быть скомпилировано в более ранних версиях, поэтому нет поломка.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.