|
Программирование >> Программирование с использованием ajax
В этом случае скомпилировать код тоже не получится, поскольку переменные перед использованием должны обязательно объявляться и инициализироваться, а переменная text в цикле for только инициализируется. Из-за этого при выходе из цикла присвоенное ей значение теряется. Однако можно внести в этот код такое изменение: int i; string text = ; for (i = 0; i < 10; i++) { text = Line + Convert.ToString(i); Console.WriteLine ( {0} , text); Console.WriteLine( Last text output in loop: {0} , text); Ha этот раз переменная text инициализируется за пределами цикла и имеется доступ к ее значению. Результат выполнения этого простого кода показан на рис. 6.6. Рис. 6.6. Результат выполнения измененного кода Здесь последнее значение, присваиваемое text в цикле, доступно и за пределами цикла. Очевидно, что понимание данной темы требует приложения несколько больших усилий. На первый взгляд не совсем ясно, почему, с учетом предыдущего примера, у переменной text после цикла не остается в качестве значения та пустая строка, которг1я была присвоена ей перед началом цикла в коде. Причина такого поведения связана с выделением памяти для переменной text, как, по сути, это делается для любой другой переменной. Одно лишь объявление переменной простого типа ни к каким особым действиям не приводит. Только при присваивании переменным значений для их хранения в памяти выделяется место. Когда эта операция по выделению памяти происходит внутри цикла, значение определяется как локальное значение и тогда за пределами цикла оно покидает свою область видимости. Даже хотя сама переменная не ограничивается циклом, то значение, которое в ней содержится, ограничивается им. Присваивание значения переменной за пределами цикла, однако, делает его локальным по отношению к главному коду и при этом все равно оставляет действительным внутри цикла. Это означает, что переменная не выходит за рамки области видимости до тех пор, пока не завершится выполнения основного блока кода, благодаря чему к содержащемуся в ней значению можно получать доступ и за пределами цикла. К счастью для программистов, компилятор С# обнаруживает проблемы, связанные с областью видимости переменных, а реагирование на генерируемые им сообщения об ошибках, действительно позволяет лучше разобраться в этой теме. И, наконец, конечно же, нужно сказать о том, какой подход является рекомендуемым. В целом считается, что лучше объявлять и инициализировать все переменные перед теми блоками кода, в которых они будут использоваться. Исключением являются лишь переменные, применяемые внутри цикла, каковые удобнее объявлять в виде части представляющего цикл блока: for (int i = 0; 1 < 10; i++) Здесь i ограничивается блоком реализующего цикл кода, но в это нет ничего страшного, поскольку доступ к этой переменной-счетчику из внешнего кода требуется крайне редко. Параметры и возвращаемые значения вместо глобальных данных в этом разделе более подробно анализируются преимущества и недостатки обмена данными с функциями через глобальные данные и через параметры и возвращаемые значения. Чтобы вспомнить, о чем идет речь, взгляните на следующий код: class Program { static void ShowDouble (ref int val) { val *= 2; Console.WriteLine ( удвоенное значение val = {0} , val) ; static void Main(string[] args) { int val = 5; Console.WriteLine( val = {0} , val); ShowDouble (ref val) ; Console.WriteLine( val = (0) , val); Этот код немного отличается от продемонстрированного в гяаве ранее, на примере использования переменной myNumber в функции Main (). Он иллюстрирует тот факт, что пе ременные вполне могут иметь идентичные имена и при этом совершенно не мешать друг другу. Это делает его более схожим со вторым приводимым здесь примером кода, что дает возможность сфокусироваться на конкретных отличиях и не обращать внимания на имена переменных. Теперь сравните его с таким кодом: class Program { static int val; static void ShowDouble () val *= 2; Console.WriteLine( удвоенное значение val = {0} , val); static void Main(string[] args) { val = 5; Console.WriteLine( val = {0} , val); ShowDouble 0 ; Console.WriteLine ( val = {0} , val); Результаты вызова обеих показанных здесь функций ShowDouble будут выглядеть идентично. Никаких жестких правил касательно того, что следует применять именно тот подход, а не другой, не существует. Оба они абсолютно допустимы, но, возможно, следующие рекомендации окажутся полезными. Прежде всего, как уже упоминалось, когда данная тема затрагивалась впервые, версия ShowDouble (), в которой используется глобальное значение, требует обязательного применения глобальной переменной val. Это немного ограничивает разносторонность функции и означает, что при желании сохранять результаты придется постоянно копировать значение этой глобальной переменной в другие переменные. Помимо этого, при таком подходе не исключена вероятность изменения глобальных данных в каком-нибудь месте в приложении, что может привести к непредсказуемым результатам (например, изменению значений без выявления проблемы до тех пор, пока не станет слишком поздно). Однако такая потеря универсальности зачастую может превращаться в преимущество. Нередко функцию требуется использовать только для какой-то одной цели, а применение хранилища глобальных данных снижает вероятность допущения в вызове функции той или иной ошибки, например, передачи не той переменной. Конечно, также можно и возразить, что подобная простота на самом деле усложняет восприятие кода. Явное указание параметров позволяет сразу же видеть, что изменяется. Например, один взгляд на вызов типа myFunction (vail, out val2) дает возможность понять, что vail и val2 являются теми важными переменными, на которые следует обратить внимание, и что по завершении выполнения функции переменной val2 будет присваиваться новое значение. Если бы функция не принимала никаких параметров, сделать подобные предположения о том, какие данные будут обрабатываться, было бы не возможно. Напоследок запомните, что применение глобальных данных не всегда представляется возможным. Позже в этой книге еще будет демонстрироваться код, хранящийся в разных файлах и/или относящийся к разным пространствам имен, которые взаимодействуют друг с другом посредством функций. В подобных случаях код часто разбивается до такой степени, что никакого очевидного варианта для места размещения глобального хранилища просто нет. Таким образом, получается, что для обмена данными можно свободно применять любой из описанных подходов. В целом рекомендуется использовать параметры, а не глобальные данные. Но, разумеется, встречаются случаи, когда подход с применением глобальных данных может оказаться более подходящим и его использование точно не будет ошибкой. Функция Main () Теперь, когда было рассмотрено большинство из простых приемов, применяемых для создания и использования функций, пришла пора более подробно рассмотреть функцию Main О . Ранее уже упоминалось о том, что функция Main () является точкой входа в любом С#-приложении и что ее выполнение охватывает выполнение всего приложения. То есть запуск приложения приводит к началу выполнения функции Main (), а завершение его работы - к завершению ее выполнения. Функция Main () может возвращать либо void, либо значение int, а также необязательно включать параметр string [ ] args, что дает возможность использовать ее в любой из следующих версий:
|
© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |