Области видимости переменных
Шапка-невидимка. Введите в окно кода такой код: Public Class Form1 Inherits System.Windows.Forms.Form Windows Form Designer generated code Dim a As Integer = 5
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim b As Integer = 4 a = b End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click a = b End Sub End Class VB подчеркнул во второй из двух процедур переменную b. Ошибка. При наведении мышки на ошибку VB выдал подсказку: Name 'b' is not declared, что означает «Имя b не объявлено». Как не объявлено?! Ведь в первой процедуре мы b объявили! В чем дело? Дело в так называемых областях видимости. Закон такой: Переменная, объявленная внутри процедуры, не видна снаружи, в том числе и из других процедур. Происходит вот что: Когда первая процедура выполняется, ее переменная b живет и здравствует, но второй процедуре от этого никакой выгоды нет, так как она сама в это время спит летаргическим сном и ждет своей очереди. Когда же мы ее будим щелчком по кнопке Button2, то оказывается, что первая процедура уже заснула, а значит и ее переменная b уничтожена. Уничтожена – не уничтожена! Какая разница, если это все равно чужая переменная, то есть принадлежащая другой процедуре?! Умный VB предвидит эту ситуацию и подчеркивает переменную b во второй процедуре, намекая, что неплохо бы ее там объявить. Ну что ж, объявим, добавив оператор во вторую процедуру: Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Dim b As Integer = 1 a = b End Sub Теперь все в порядке и все работает. Стеклянные стены. Вопрос: а почему VB не жаловался на переменную a? Ведь мы ее не объявляли ни в одной процедуре. Ответ: а потому что мы ее объявили вне процедур. Закон такой: Переменная, объявленная вне процедур, видна изо всех процедур окна кода. Создается и инициализируется такая переменная раньше тех, что объявлены в процедурах, а уничтожается позже. Тезки. Еще один вопрос, «философский»: правда ли, что переменная b из первой процедуры и переменная b из второй процедуры – это одна и та же переменная, время от времени рождающаяся и умирающая, или же это «тезки» – две разные переменные, только с одним именем? Ответ однозначный: верно второе. В доказательство рассмотрим ситуацию, когда обе процедуры работают одновременно: Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click Dim b As Integer b = 11 Процедура() Debug.WriteLine(b) b = 4 End Sub
Sub Процедура() Dim b As Integer b = 8 Debug.WriteLine(b) End Sub После щелчка по кнопке Button3 компьютер напечатает вот что: Запустите проект в пошаговом режиме. После выполнения оператора b=11 компьютер прыгает на процедуру пользователя, создает ее переменную b и начинает процедуру выполнять. Обратите внимание, что выполнение первой процедуры при этом не завершено, а значит и переменная b этой процедуры не уничтожена. К сожалению, пошаговый режим не показывает нам разницу значений этих переменных, однако оператор Debug.WriteLine(b) делает это безошибочно. Первой выполняется печать в процедуре пользователя и, естественно, печатается 8. Затем компьютер возвращается в первую процедуру, прямо к выполнению ее оператора Debug.WriteLine(b). Если бы переменная b была одна на обе процедуры, то конечно была бы напечатана еще раз 8. Однако у каждой из процедур своя переменная, а чужая вообще не видна, поэтому оператор Debug.WriteLine(b) спокойно печатает свою переменную b, которая равна 11. Итак: Переменные с одинаковыми именами, объявленные в разных процедурах, являются разными переменными. Не путайте. Терминология. Подводим итоги: Мы обнаружили две области видимости переменных: конкретная процедура или все окно кода. Если переменные объявлены внутри процедуры, то они и использованы могут быть только внутри нее. Их зона видимости – эта конкретная процедура. Называют такие переменные локальными переменными. Параметры процедуры тоже являются локальными переменными в этой процедуре, так как они объявлены именно в ее заголовке. Если переменные объявлены вне процедур, то они могут быть использованы во всем окне кода внутри любой процедуры. Называют такие переменные модульными переменнымиили переменными уровня модуля. О причине такой терминологии поговорим попозже (21.9). Тезки из разных областей. Теперь вопрос относительно модульной переменной: что будет, если нам захотелось назвать одинаковыми именами локальную переменную и переменную уровня модуля? Проверим: Public Class Form1 Inherits System.Windows.Forms.Form Windows Form Designer generated code Dim a As Integer = 5
Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click Dim a As Integer = 44 Debug.WriteLine(a) End Sub End Class Здесь компьютер напечатает Спрашивается: что это было – одна и та же переменная или разные? А если разные, то почему предпочли локальную, ведь из процедуры видны обе? Или нет? Ответом будет закон «Своя рубашка ближе к телу»: Если к вам в гости пришли Петя и Коля, а у вас в доме уже живет член семьи Коля, то вы пришедшего Колю не пускаете на порог. А с Петей все нормально. В переводе на язык программистов: Локальная и модульная переменные с одинаковыми именами являются разными переменными, причем модульная переменная не видна из процедуры, где объявлена локальная переменная с тем же именем. Говорят: локальная переменная затеняет в своей процедуре модульную с тем же именем. Тщательно пережевывайте пищу. Если вы поняли все, что я только что объяснял, то без компьютера определите, что напечатает программа: Public Class Form1 Inherits System.Windows.Forms.Form Windows Form Designer generated code Dim x As Integer 'x - модульная переменная Dim z As Integer 'z - модульная переменная
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click x = 1 : z = 2 'x и z - модульные переменные B() Debug.WriteLine(x & " " & z) 'x и z - модульные переменные End Sub
Private Sub B() Dim x As Integer 'x - локальная переменная Dim y As Integer 'y - локальная переменная x = 20 : y = 30 : z = 40 End Sub End Class Ответ приведен в конце подраздела. Если с ответом не сходится, то значит вы поняли не все, и вот вам пояснение: Оператор Debug.WriteLine(x & " " & z) находится снаружи процедуры В, и поэтому локальная переменная х=20, объявленная внутри В, из него не видна. Зато прекрасно видна модульная переменная х=1, которую он и печатает. Переменная же z не объявлена внутри В, поэтому она является модульной переменной, и оператор z=40 с полным правом меняет ее значение с 2 на 40. А теперь приведу длинное пояснение «ближе к железу»: Переменная х, объявленная снаружи процедуры, это совсем другая переменная, чем х, объявленная в процедуре, и помещаются эти переменные в разных местах памяти. Поэтому и не могут друг друга испортить. Вы можете вообразить, что это переменные с разными именами xмод и xлок. Переменная, объявленная снаружи процедуры, видна из любой процедуры окна кода и каждая процедура может ее испортить. Однако, когда процедура натыкается на переменную x, объявленную внутри самой этой процедуры, то она, благодаря описанному выше механизму, работает только с ней и не трогает переменную x, объявленную снаружи. Вот порядок выполнения программы: В оперативной памяти VB отводит ячейки под Х мод и Z мод. Процедура Button1_Click начинает выполняться с присвоения значений Х мод = 1 и Z мод = 2. Почему мод, а не лок? Потому что переменные с именами X и Z в процедуре Button1_Click не объявлены, а значит волей-неволей процедуре приходится пользоваться модульными переменными. Вызывается процедура В. При этом в оперативной памяти отводится место под Х лок и У лок. Присваиваются значения Х лок = 20, У лок = 30 и Z мод = 40. Программа выходит из процедуры В. При этом исчезают переменные Х лок (20) и У лок (30). А Z мод (40) остается. Компьютер печатает Х мод = 1 и Z мод = 40. Таким образом программа напечатает 1 и 40.
Популярное: Как вы ведете себя при стрессе?: Вы можете самостоятельно управлять стрессом! Каждый из нас имеет право и возможность уменьшить его воздействие на нас... Почему двоичная система счисления так распространена?: Каждая цифра должна быть как-то представлена на физическом носителе... Почему люди поддаются рекламе?: Только не надо искать ответы в качестве или количестве рекламы... ©2015-2024 megaobuchalka.ru Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. (535)
|
Почему 1285321 студент выбрали МегаОбучалку... Система поиска информации Мобильная версия сайта Удобная навигация Нет шокирующей рекламы |