Почему этот код работает? Я использую C # 8 с Visual Studio 2019.
Вы ответили на свой вопрос! Это потому, что вы используете C # 8.
Правило от C # 1 до 7 гласило: простое имя не может означать две разные вещи в одной локальной области. (Фактическое правило было немного более сложным, чем это, но описывало, как это утомительно; подробности см. В спецификации C #.)
Цель этого правила состояла в том, чтобы предотвратить ситуацию, о которой вы говорите в своем примере, когда очень легко запутаться в значении местного значения. В частности, это правило было разработано для предотвращения таких недоразумений, как:
class C
{
int x;
void M()
{
x = 123;
if (whatever)
{
int x = 356;
...
И сейчас у нас возникла ситуация, когда внутри тела M
, x
значит, this.x
и местное x
.
Несмотря на благие намерения, с этим правилом было несколько проблем:
- Это не было реализовано по спецификации. Были ситуации, когда простое имя могло использоваться как, скажем, и тип, и свойство, но они не всегда отмечались как ошибки, поскольку логика обнаружения ошибок была ошибочной. (См. ниже)
- Сообщения об ошибках были смущенно сформулированы и непоследовательны. Для этой ситуации было несколько разных сообщений об ошибках. Они непоследовательно опознали преступника; то есть иногда внутреннее использование будет вызвано, иногда внешнее , а иногда это просто сбивает с толку.
Я попытался переписать Roslyn, чтобы разобраться в этом; Я добавил несколько новых сообщений об ошибках и сделал старые согласованными относительно того, где сообщалось об ошибке. Однако, это усилие было слишком мало, слишком поздно.
Команда C # решила для C # 8, что все правило вызывает больше путаницы, чем предотвращает, и это правило было удалено из языка. (Спасибо Джонатону Чейзу за определение, когда произошла отставка.)
Если вам интересно узнать историю этой проблемы и то, как я пытался ее исправить, посмотрите статьи, которые я написал об этом:
https://ericlippert.com/2009/11/02/simple-names-are-not-so-simple/
https://ericlippert.com/2009/11/05/simple-names-are-not-so-simple-part-two/
https://ericlippert.com/2014/09/25/confusing-errors-for-a-confusing-feature-part-one/
https://ericlippert.com/2014/09/29/confusing-errors-for-a-confusing-feature-part-two/
https://ericlippert.com/2014/10/03/confusing-errors-for-a-confusing-feature-part-three/
В конце третьей части я отметил, что между этой функцией и функцией «Цветовой цвет» также было взаимодействие, то есть функция, которая позволяет:
class C
{
Color Color { get; set; }
void M()
{
Color = Color.Red;
}
}
Здесь мы использовали простое имя Color
для ссылки на оба типа this.Color
и перечислимый тип Color
; в соответствии со строгим прочтением спецификации, это должно быть ошибкой, но в этом случае спецификация была неправильной, и было намерение разрешить ее, поскольку этот код недвусмыслен, и было бы неприятно заставить разработчика изменить его.
Я никогда не писал эту статью, описывающую все странные взаимодействия между этими двумя правилами, и сейчас было бы немного бессмысленно делать это!
x
параметр этого метода выходит из области видимости. Смотрите sharplab для примера.