Насколько я понимаю, первый пример должен быть в порядке.
Вы хорошо понимаете сферу. Это не ошибка области видимости. Это непоследовательное использование простой ошибки имени.
int i = 10; // ошибка, 'i' уже существует
Это не та ошибка, о которой сообщается . Сообщается об ошибке: «Локальная переменная с именем i не может быть объявлена в этой области действия , поскольку она придала бы другое значение i, которое уже используется в дочерней области для обозначения чего-то другого "
Сообщение об ошибке сообщает вам, что это за ошибка; прочитайте сообщение об ошибке еще раз. Нигде не говорится, что существует конфликт между декларациями; он говорит, что ошибка , потому что это меняет значение простого имени . Ошибка: , а не переопределение; совершенно законно иметь две вещи в двух разных областях, которые имеют одно и то же имя, даже если эти области гнездятся. То, что не допустимо, состоит в том, что одно простое имя означает две разные вещи во вложенных пространствах объявлений локальных переменных .
Вы получите сообщение об ошибке «локальная переменная с именем i уже определена в этой области», если вместо этого вы сделали что-то вроде
int i = 10;
int i = 10;
Конечно, «я» либо в области видимости, либо нет.
Конечно, но что с того? Находится ли данное i в области или нет, не имеет значения. Например:
class C
{
int i;
void M()
{
string i;
Совершенно законно. Внешний i находится в области видимости на всем протяжении M. Нет никакой проблемы с объявлением локального i, который затеняет внешнюю область видимости. Что было бы проблемой, если бы вы сказали
class C
{
int i;
void M()
{
int x = i;
foreach(char i in ...
Потому что теперь вы использовали i для обозначения двух разных вещей в двух вложенных пространствах объявления локальных переменных - переменной цикла и поля. Это сбивает с толку и подвержено ошибкам, поэтому мы делаем его незаконным.
Есть ли что-то неочевидное в области видимости, которую я не понимаю, и это означает, что компилятор не может решить эту проблему?
Я не понимаю вопроса. Очевидно, компилятор способен полностью проанализировать программу; если компилятор не может разрешить значение каждого использования i, то как он может сообщить об ошибке? Компилятор полностью может определить, что вы использовали «i» для обозначения двух разных вещей в то же самое пространство объявления локальной переменной, и сообщает об ошибке соответственно.