Почему этот код работает? Я использую 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
; согласно строгому прочтению спецификации это должно быть ошибкой, но в данном случае спецификация была неправильной, и намерение состояло в том, чтобы разрешить это, поскольку этот код недвусмысленен и было бы неприятно заставить разработчика изменить его.
Я никогда не писал эту статью, описывающую все странные взаимодействия между этими двумя правилами, и было бы бессмысленно делать это сейчас!
person
Eric Lippert
schedule
29.01.2020
x
этого метода перемещается за пределы области видимости. См sharplab для примера. - person Lasse V. Karlsen   schedule 29.01.2020