Каково определяющее свойство локальной переменной?
Если вы спросите у десяти C#-программистов о том, что такое «локальная переменная», то вы получите десять разных ответов. Самым распространенным ответом будет, что локальная переменная – это «ячейка памяти в стеке». Однако это описывают локальную переменную в терминах деталей реализации; в спецификации языка C# ничего не говорится о том, что локальные переменные должны храниться в структуре данных под названием «стек», или о наличии только одного стека у одного потока. (Конечно, локальные переменные часто хранятся в регистрах, которые не являются стеком.)
Другим ответом, менее обремененным деталями реализации, может быть следующий: локальная переменная – это переменная, хранящаяся в ячейке памяти, «выделенной во временном хранилище». Т.е. локальная переменная – это переменная с коротким временем жизни; время жизни локальной переменной завершается, когда управление покинет локальную область видимости.
Однако, это тоже неправда. Спецификация языка C# удивительно неоднозначна по поводу времени жизни «обыкновенных» локальных переменных и в ней ничего не говорится о подобных ограничениях. Оптимизатор jit-компилятора может самостоятельно изменять время жизни локальных переменных; они могут освобождаться раньше или позже обычного. Кроме того, в спецификации говорится о том, что в случае необходимости время жизни некоторых переменных может быть продлено после того, как управление покинет метод, содержащий локальную переменную. Например, переменные, объявленные в блоке итератора (iterator block) будут «жить» после того, как управление будет передано из блока итератора; они будут освобождены только при освобождении самого итератора. Переменные, захваченные (closed-over) лямбда-выражением, ведут себя аналогичным образом; они живут, по крайней мере столько же, сколько и захвативший их делегат. В будущей версии языка C#, время жизни локальных переменных, объявленных в асинхронном блоке (async block), также будет продлено; локальные переменные будут жить после того, как асинхронный метод вернет управление вызывающему коду после «await». (А поскольку в некоторых случаях метод может продолжить свое выполнение не в том же самом потоке, то лучше бы им не храниться в стеке!)
Так если локальные переменные – это не «переменные на стеке» и не «короткоживущие переменные», тогда что же это такое?
Ответ на этот вопрос, конечно же, очевиден. Определяющей (defining) характеристикой локальной переменной является то, что она может быть использоваться лишь в блоке, в котором она объявлена; т.е. в локальном блоке. Важным свойством локальной переменной является то, что она является лишь закрытой деталью реализации тела метода. Имя локальной переменной никак не может быть использовано за пределами лексической области видимости метода.