Чому цей код працює? Я використовую 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 для прикладу.