Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Тип void. 3 страница




Рассмотрим еще ситуацию, приводящую к конфликту. Первый аргумент в соответствии с правилами требует вызова одной реализации, а второй аргумент будет настаивать на вызове другой реализации. Возникнет коллизия, не разрешимая правилами C# и приводящая к ошибке периода компиляции. Коллизию требуется устранить, например, как это сделано в примере. Обратите внимание, обе реализации допустимы и будь только одна из них, ошибки бы не возникало.

Явные преобразования

Как уже говорилось, явные преобразования могут быть опасными из-за потери точности. Поэтому они выполняются по указанию программиста, – на нем лежит вся ответственность за результаты.

Преобразования строкового типа

Важным классом преобразований являются преобразования в строковый тип и наоборот. Преобразования в строковый тип всегда определены, поскольку, напомню, все типы являются потомками базового класса object, а, следовательно, обладают методом ToString (). Для встроенных типов определена подходящая реализация этого метода. В частности, для всех подтипов арифметического типа метод ToString () возвращает в подходящей форме строку, задающую соответствующее значение арифметического типа. Заметьте, метод ToString можно вызывать явно, но, если явный вызов не указан, то он будет вызываться неявно, всякий раз, когда по контексту требуется преобразование к строковому типу. Вот соответствующий пример:

/// <summary>

/// Демонстрация преобразования в строку

/// данных различного типа.

/// </summary>

public void ToStringTest()

{

s ="Владимир Петров ";

s1 =" Возраст: "; ux = 27;

s = s + s1 + ux.ToString();

s1 =" Зарплата: "; dy = 2700.50;

s = s + s1 + dy.ToString();

WhoIsWho("s",s);

}

Здесь для переменной ux метод был вызван явно, а для переменной dy он вызывается автоматически. Результат работы этой процедуры показан на рис. 4.3:

Рис. 4.3. Вывод на печать результатов теста ToStringTest

Преобразования из строкового типа в другие типы, например, в арифметический тип, должны выполняться явно. Но явных преобразований между арифметикой и строками не существуют. Должны работать другие механизмы. И они в C# имеются. Для этой цели можно использовать соответствующие методы класса Convert библиотеки FCL, встроенного в пространство имен System. Приведу соответствующий пример:

/// <summary>

/// Демонстрация преобразования строки

/// в данные различного типа.

/// </summary>

public void FromStringTest()

{

s ="Введите возраст ";

Console.WriteLine(s);

s1 = Console.ReadLine();

ux = Convert.ToUInt32(s1);

WhoIsWho("Возраст: ",ux);

s ="Введите зарплату ";

Console.WriteLine(s);

s1 = Console.ReadLine();

dy = Convert.ToDouble(s1);

WhoIsWho("Зарплата: ",dy);

}

Этот пример демонстрирует ввод с консоли данных разных типа. Данные, читаемые с консоли методом ReadLine или Read, всегда представляют собой строку, которую затем необходимо преобразовать в нужный тип. Тут то и вызываются соответствующие методы класса Convert. Естественно, для успеха преобразования преобразуемая строка должна содержать значение, записанное в формате, допускающем подобное преобразование. Заметьте, например, при записи значения числа для выделения дробной части должна использоваться запятая, а не точка; в противном случае возникнет ошибка периода выполнения.

На рис. 4.4 показаны результаты вывода и ввода данных с консоли при работе этой процедуры:

Рис. 4.4. Вывод на печать результатов теста FromStringTest

Преобразования и класс Convert

Класс Convert, определенный в пространстве имен System, играет важную роль, обеспечивая необходимые преобразования между различными типами. Напомню, что внутри арифметического типа можно использовать более простой, скобочный способ приведения к нужному типу. Но таким способом нельзя привести, например, переменную типа string к типу int, Оператор присваивания: ux = (int) s1; приведет к ошибке периода компиляции. Здесь необходим вызов метода ToInt32 класса Convert, как это сделано в последнем примере предыдущего раздела.

Методы класса Convert поддерживают общий способ выполнения преобразований между типами. Класс Convert содержит 15 статических методов вида To<Type> (ToBoolean (),… ToUInt64 ()), где Type может принимать значения от Boolean до UInt64 для всех встроенных типов, перечисленных в таблице 3-1. Единственным исключением является тип object, – метода ToObject нет по понятным причинам, поскольку для всех типов существует неявное преобразование к типу object. Среди других методов отмечу общий статический метод ChangeType, позволяющий преобразование объекта к некоторому заданному типу.

Отмечу возможность преобразования к системному типу DateTime, который хотя и не является встроенным типом языка C#, но допустим в программах, как и любой другой системный тип. Приведу простейший пример работы с этим типом:

//System type: DateTime

System.DateTime dat = Convert.ToDateTime("15.03.2003");

Console.WriteLine("Date = {0}", dat);

Результатом вывода будет строка:

Date = 15.03.2003 0:00:00

Все методы To<Type> класса Convert перегружены и каждый из них имеет, как правило, более десятка реализаций с аргументами разного типа. Так что фактически эти методы задают все возможные преобразования между всеми встроенными типами языка C#.

Кроме методов, задающих преобразования типов, в классе Convert имеются и другие методы, например, задающие преобразования символов Unicode в однобайтную кодировку ASCII, преобразования значений объектов и другие методы. Подробности можно посмотреть в справочной системе.

Проверяемые преобразования

Уже говорилось о том, что при выполнении явных преобразований могут возникать нежелательные явления, например, потеря точности. Я говорил, что вся ответственность за это ложится на программиста, но легче ему от этого не становится. А какую часть этого бремени может взять на себя язык программирования? Что можно предусмотреть для обнаружения ситуаций, когда такие явления все-таки возникают? В языке C# имеются необходимые для этого средства.

Язык C# позволяет создать проверяемый блок, в котором будет осуществляться проверка результата вычисления арифметических выражений. Если результат вычисления значения источника выходит за диапазон возможных значений целевой переменной, то возникнет исключение (говорят также, будет выброшено исключение) соответствующего типа. Если предусмотрена обработка исключения, то дальнейшее зависит от обработчика исключения. В лучшем случае программа сможет продолжить корректное выполнение. В худшем, – она остановится, и выдаст информацию об ошибке. Заметьте, не произойдет самого опасного – продолжения работы программы с неверными данными.

Синтаксически проверяемый блок предваряется ключевым словом checked. В теле такого блока арифметические преобразования проверяются на допустимость. Естественно, такая проверка требует дополнительных временных затрат. Если группа операторов в теле такого блока нам кажется безопасной, то их можно выделить в непроверяемый блок, используя ключевое слово unchecked. Замечу еще, что и в непроверяемом блоке при работе методов Convert все опасные преобразования проверяются и приводят к выбрасыванию исключений. Приведу пример, демонстрирующий все описанные ситуации:

/// <summary>

/// Демонстрация проверяемых и непроверяемых преобразований

/// Опасные проверяемые преобразования приводят к исключениям,

/// Опасные непроверяемые преобразования

/// приводят к неверным результатам, что совсем плохо.

/// </summary>

public void CheckUncheckTest()

{

x = -25^2;

WhoIsWho ("x", x);

b= 255;

WhoIsWho("b",b);

//Проверяемые опасные преобразования.

//Возникают исключения, перехватываемые catch-блоком.

checked

{

try

{

b += 1;

}

catch (Exception e)

{

Console.WriteLine("Переполнение при вычислении b");

Console.WriteLine(e);

}

try

{

b = (byte)x;

}

catch (Exception e)

{

Console.WriteLine("Переполнение при преобразовании к byte");

Console.WriteLine(e);

}

//непроверяемые опасные преобразования

unchecked

{

try

{

b +=1;

WhoIsWho ("b", b);

b = (byte)x;

WhoIsWho ("b", b);

ux= (uint)x;

WhoIsWho ("ux", x);

Console.WriteLine("Исключений нет, но результаты не верны!");

}

catch (Exception e)

{

Console.WriteLine("Этот текст не должен появляться");

Console.WriteLine(e);

}

//автоматическая проверка преобразований в Convert

//исключения возникают, несмотря на unchecked

try

{

b = Convert.ToByte(x);

}

catch (Exception e)

{

Console.WriteLine("Переполнение при преобразовании к byte!");

Console.WriteLine(e);

}

try

{

ux= Convert.ToUInt32(x);

}

catch (Exception e)

{

Console.WriteLine("Потеря знака при преобразовании к uint!");

Console.WriteLine(e);

}

}

}

}

Исключения и охраняемые блоки. Первое знакомство

В этом примере мы впервые встречаемся с охраняемыми try-блоками. Исключениям и способам их обработки посвящена отдельная лекция, но не стоит откладывать надолго знакомство со столь важным механизмом. Как показывает практика программирования, любая вызываемая программа не гарантирует, что в процессе ее работы не возникнут какие-либо неполадки, в результате чего она не сможет выполнить свою часть контракта. Исключения являются нормальным способом уведомления об ошибках в работе программы. Возникновение ошибки в работе программы должно приводить к выбрасыванию исключения соответствующего типа, следствием чего является прерывание нормального хода выполнения программы и передача управления обработчику исключения – стандартному или предусмотренного самой программой.

Заметьте, рекомендуемый стиль программирования в C# отличается от стиля принятого в языках С/C++, где функция, в которой возникла ошибка завершается нормальным образом, уведомляя об ошибке в возвращаемом значении результата. Вызывающая программа должна анализировать результат, чтобы понять была ли ошибка в работе вызванной функции и какова ее природа. При программировании в стиле C# ответственность за обнаружение ошибок лежит на вызванной программе. Она должна не только обнаружить ошибку, но и явно сообщить о ней, выбрасывая исключение соответствующего типа..Вызываемая программа должна попытаться исправить последствия ошибки в обработчике исключения. Подробности смотри в лекции про исключения???

В состав библиотеки FCL входит класс Exception, свойства и методы которого позволяют работать с исключениями как с объектами, получать нужную информацию, дополнять объект собственной информацией. У класса Exception большое число потомков, каждый из которых описывает определенный тип исключения. При проектировании собственных классов можно параллельно проектировать и классы, задающие собственный тип исключений, который может выбрасываться в случае ошибок при работе методов класса. Создаваемый класс исключений должен быть потомком класса Exception.

Если в некотором модуле предполагается возможность появления исключений, то разумно предусмотреть и их обработку. В этом случае в модуле создается охраняемый try-блок, предваряемый ключевым словом try. Вслед за этим блоком следует один или несколько блоков, обрабатывающих исключения – catch-блоков. Каждый catch-блок имеет формальный параметр класса Exception или одного из его потомков. Если в try-блоке возникает исключение типа T, то catch-блоки начинают конкурировать в борьбе за перехват исключения. Первый по порядку catch-блок, тип формального аргумента которого согласован с типом T – совпадает с ним или является его потомком – захватывает исключение и начинает выполняться. Поэтому порядок написания catch-блоков важен. Вначале должны идти специализированные обработчики. Универсальным обработчиком является catch-блок с формальным параметром родового класса Exception, согласованным с исключением любого типа T. Универсальный обработчик, если он есть, стоит последним, поскольку захватывает исключение любого типа.

Конечно, плохо, когда в процессе работы той или иной процедуры возникает исключение. Однако его появление еще не означает, что процедура не сможет выполнить свой контракт. Исключение может быть нужным образом обработано, после чего продолжится нормальный ход вычислений приложения. Гораздо хуже, когда возникают ошибки в работе процедуры, не приводящие к исключениям. Тогда работа продолжается с неверными данными без исправления ситуации и даже без уведомления о возникновении ошибки. Наш пример показывает, что вычисления в C# могут быть небезопасными и следует применять специальные средства языка, такие, как, например, checked-блоки, чтобы избежать появления подобных ситуаций.

Вернемся к обсуждению нашего примера. Здесь как в проверяемых, так и не проверяемых блоках находятся охраняемые блоки с соответствующими обработчиками исключительных ситуаций. Во всех случаях применяется универсальный обработчик, захватывающий любое исключение в случае его возникновения в try-блоке. Сами обработчики являются простыми уведомителями, они лишь сообщают об ошибочной ситуации, не пытаясь исправить ее.

Опасные вычисления в охраняемых проверяемых блоках

Такая ситуация возникает в первых двух try-блоках нашего примера. Эти блоки встроены в проверяемый checked-блок. В каждом из них используются опасные вычисления, приводящие к неверным результатам. Так при присваивании невинного выражения b+1 из-за переполнения переменная b получает значение 0, а не 256. Поскольку вычисление находится в проверяемом блоке, то ошибка вычислений обнаруживается и результатом является вызов исключения. Поскольку все это происходит в охраняемом блоке, то управление перехватывается и обрабатывается в соответствующем catch-блоке. Эту ситуацию следует отнести к нормальному, разумно построенному процессу вычислений.

Опасные вычисления в охраняемых непроверяемых блоках

Такую ситуацию демонстрирует третий try-блок нашего примера, встроенный в непроверяемый unchecked-блок. Здесь участвуют те же самые опасные вычисления. Но теперь их корректность не проверяется, они не вызывают исключений, как следствие, соответствующий catch-блок не вызывается. Результаты вычислений при этом неверны, но никаких уведомлений об этом нет. Это самая плохая ситуация, которая может случиться при работе наших программ.

Заметьте, проверку переполнения в арифметических вычислениях можно включить не только с помощью создания checked-блоков, но и задав свойство checked проекта. По умолчанию это свойство выключено. Как правило, это свойство проекта всегда включается в процессе разработки и отладки проекта. В законченной версии проекта свойство отключается, поскольку полная проверка всех преобразований требует определенных накладных расходов, увеличивая время работы. В законченной версии остаются проверяемые блоки там, где такой контроль действительно необходим.

Область действия проверки или ее отключения можно распространить и на отдельное выражение. В этом случае спецификаторы checked и unchecked предшествуют выражению, заключенному в круглые скобки. Такое выражение называется проверяемым (непроверяемым) выражением, а checked и unchecked рассматриваются как операции, допустимые в выражениях.

Опасные преобразования и методы класса Convert

Явно выполняемые преобразования по определению относятся к опасным. Явные преобразования можно выполнять по-разному. Синтаксически наиболее просто выполнить приведение типа – кастинг, явно указав тип приведения, как это сделано в только что рассмотренном примере. Но если это приведение делается в непроверяемом блоке, последствия могут быть самыми печальными. Поэтому такой способ приведения типов следует применять с большой осторожностью. Надежнее преобразования типов выполнять более универсальным способом, используя стандартный встроенный класс Convert, специально спроектированный для этих целей.

В нашем примере четвертый и пятый try-блоки встроены в непроверяемый unchecked-блок. Но опасные преобразования реализуются методами класса Convert, которые сами проводят проверку и при необходимости выбрасывают исключения, что и происходит в нашем случае.

На рис. 4.5 показаны результаты работы процедуры CheckUncheckTest. Их анализ способствует лучшему пониманию рассмотренных нами ситуаций.

Рис. 4.5. Вывод на печать результатов теста CheckUncheckTest

На этом, пожалуй, пора поставить точку в обсуждении системы типов языка C#. За получением тех или иных подробностей, как всегда, следует обращаться к справочной системе.

Вариант 1

7. Преобразования между значимыми и ссылочными типами:

q всегда допустимы;

q никогда не допустимы;

q должны быть явными;

q используют операции boxing и unboxing;

q могут быть неявными.

8. Отметьте истинные высказывания:

q существует неявное преобразование переменных арифметического типа в объекты;

q существует неявное преобразование объектов в переменные арифметического типа;

q существует явное преобразование объектов в переменные арифметического типа;

q в зависимости от контекста переменная арифметического типа представляет собой объект.

9. В проверяемом блоке проверяется корректность:

q всех преобразований типов;

q преобразований внутри арифметического типа;

q только преобразований, выполняемых методом Parse;

q только преобразований, выполняемых методами класса Convert.

Вариант 2

10. Методы класса Convert осуществляют преобразования:

q только внутри арифметического типа;

q между любыми типами;

q только между строковым и арифметическим типом;

q для фиксированного набора типов.

11. Отметьте истинные высказывания:

q у класса Exception нет потомков;

q у класса Exception фиксированное число потомков;

q можно создавать собственные классы – потомки класса Exception;

q объекты класса Exception автоматически создаются в охраняемых блоках при возникновении исключительных ситуаций;

q catch-блоки выполняются в порядке их следования.

12. Охраняемый try-блок:

q запрещает появление исключительных ситуаций;

q обрабатывает возникающие в нем исключительные ситуации;

q если в нем возникает исключительная ситуация, то блок завершается;

q если блок завершается, то в нем возникает исключительная ситуация;

q всегда сопровождается одним или несколькими catch-блоками.

Вариант 3

10. Явное преобразование типа может быть выполнено:

q статическим методом Parse;

q статическим методом Convert;

q статическими методами класса Convert;

q статическими методами класса Parse;

q приведением типа;

q разрешено только для значимых типов.

11. Отметьте истинные высказывания:

q присваивание ссылочной переменной объекта значимого типа требует явного преобразования;

q преобразование в строку определено для любого объекта X класса Т, созданного пользователем;

q объекту базового класса Object можно присвоить объект класса Т, созданного пользователем;

q исключения, возникающие в охраняемом try-блоке, всегда перехватываются catch-блоком, сопровождающим охраняемый блок.

12. При включенной опции компилятора /checked проверка корректности преобразований типов выполняется:

q для всех преобразований во всем проекте;

q для всех преобразований во всем проекте, исключая непроверяемые блоки;

q только для преобразований арифметического типа во всем проекте, исключая непроверяемые блоки и непроверяемые выражения;

q для всех преобразований во всем проекте, исключая непроверяемые блоки и непроверяемые выражения.

 

Лекция 5. Переменные и выражения

Объявление переменных. Синтаксис объявления. Инициализация. Время жизни и область видимости. Где объявляются переменные? Локальные и глобальные переменные. Есть ли глобальные переменные в C#?. Константы.

Ключевые слова: переменная; синтаксис объявления; объявитель; инициализация; объявление с отложенной инициализацией; время жизни; область видимости; поля; глобальные переменные; локальные переменные; конфликт имен; константы.

Объявление переменных

В предыдущей лекции рассматривались типы языка C#. Естественным продолжением этой темы является рассмотрение переменных языка. Переменные и типы – тесно связанные понятия. С объектной точки зрения переменная – это экземпляр типа. Скалярную переменную можно рассматривать как сущность, обладающую именем, значением и типом. Имя и тип задаются при объявлении переменной и остаются неизменными на все время ее жизни. Значение переменной может меняться в ходе вычислений, эта возможность вариации значений и дало имя понятию переменная (Variable) в математике и программировании. Получение начального значения переменной называется ее инициализацией. Важной новинкой языка C# является требование обязательной инициализации переменной до начала ее использования. Попытка использовать неинициализированную переменную приводит к ошибкам, обнаруживаемым еще на этапе компиляции. Инициализация переменных, как правило, выполняется в момент объявления, хотя и может быть отложена.

В предыдущей лекции обсуждалась тесная связь типов и классов в языке C#. Не менее тесная связь существует между переменными и объектами. Так что, когда речь идет о переменной значимого типа, то во многих ситуациях она может играть роль объекта некоторого класса. В этой лекции обсуждение будет связано со скалярными переменными встроенных типов. Все переменные, прежде чем появиться в вычислениях, должны быть объявлены. Давайте рассмотрим, как это делается в C#.

Проект Variables

Как обычно, для рассмотрения примеров построен специальный проект. Для примеров данной лекции это консольный проект с именем Variables. Построенный по умолчанию класс Class1 содержит точку входа Main. Добавленный в проект класс Testing содержит набор скалярных переменных и методов, тестирующих разные аспекты работы со скалярными переменными в C#. В процедуре Main создается объект класса Testing и поочередно вызываются его методы, каждый из которых призван проиллюстрировать те или иные моменты работы.

Синтаксис объявления

Общий синтаксис объявления сущностей в C# похож на синтаксис объявления в C++, хотя и имеет ряд отличий. Вот какова общая структура объявления:

[<атрибуты>] [<модификаторы>] <тип> <объявители>;

Об атрибутах – этой новинке языка C# пойдет речь в отдельной лекции. Модификаторы будут появляться по мере необходимости. При объявлении переменных чаще всего задаются модификаторы доступа – public, private и другие. Если атрибуты и модификаторы могут и не указываться в объявлении, то задание типа необходимо всегда. Ограничимся пока рассмотрением уже изученных встроенных типов. Когда в роли типа выступают имена типов из таблицы 3-1, то это означает, что объявляются простые скалярные переменные. Структурные типы – массивы, перечисления, структуры и другие пользовательские типы будут изучаться в последующих лекциях.

При объявлении простых переменных указывается их тип и список объявителей, где объявитель – это имя или имя с инициализацией. Список объявителей позволяет в одном объявлении задать несколько переменных одного типа. Если объявитель задается именем переменной, то имеет место объявление с отложенной инициализацией. Хороший стиль программирования предполагает задание инициализации переменной в момент ее объявления. Инициализацию можно осуществлять двояко – обычным присваиванием или в объектной манере. Во втором случае для переменной используется конструкция new и вызывается конструктор по умолчанию. Процедура SimpleVars класса Testing иллюстрирует различные способы объявления переменных и простейшие вычисления над ними:

public void SimpleVars()

{

//Объявления локальных переменных

int x, s; //без инициализации

int y =0, u = 77; //обычный способ инициализации

//допустимая инициализация

float w1=0f, w2 = 5.5f, w3 =w1+ w2 + 125.25f;

//допустимая инициализация в объектном стиле

int z= new int();

// Недопустимая инициализация.

//Конструктор с параметрами не определен

//int v = new int(77);

 

x=u+y; //теперь x инициализирована

if(x> 5) s = 4;

for (x=1; x<5; x++)s=5;

//Инициализация в if и for не рассматривается,

//Поэтому s считается неинициализированной переменной

//Ошибка компиляции:

//использование неинициализированной переменной

//Console.WriteLine("s= {0}",s);

}// SimpleVars

В первой строке объявляются переменные x, s с отложенной инициализацией. Заметьте, и это важно, всякая попытка использовать еще не инициализированную переменную в правых частях операторов присваивания, в вызовах функций, вообще в вычислениях приводит к ошибке еще на этапе компиляции.

Последующие объявления переменных эквивалентны по сути, но демонстрируют два стиля инициализации – обычный и объектный. Обычная форма инициализации предпочтительнее не только в силу своей естественности, но она и более эффективна, поскольку в этом случае инициализирующее выражение может быть достаточно сложным с переменными и функциями. На практике объектный стиль для скалярных переменных используется редко. Вместе с тем полезно понимать, что объявление с инициализацией int y =0 можно рассматривать как создание нового объекта (new) и вызова для него конструктора по умолчанию. При инициализации в объектной форме может быть вызван только конструктор по умолчанию, другие конструкторы с параметрами для встроенных типов не определены. В примере закомментировано объявление переменной v с инициализацией в объектном стиле, приводящее к ошибке, где делается попытка дать переменной значение, передавая его конструктору в качестве параметра.

Откладывать инициализацию не стоит, как показывает пример с переменной s, объявленной с отложенной инициализацией. В вычислениях она дважды получает значение – один раз в операторе if, другой – в операторе цикла for. Тем не менее, при компиляции возникнет ошибка, утверждающая, что в процедуре WriteLine делается попытка использовать неинициализированную переменную s. Связано это с тем, что для операторов if и for на этапе компиляции не вычисляются условия, зависящие от переменных. Поэтому компилятор предполагает худшее – условия ложны, инициализация s в этих операторах не происходит. А за инициализацией наш компилятор следит строго, ты так и знай!

Время жизни и область видимости переменных

Давайте рассмотрим такие важные характеристики переменных, как время их жизни и область видимости. Зададимся вопросом, как долго живут объявленные переменные и в какой области программы видимы их имена? Ответ на эти вопросы зависит от того, где и как, в каком контексте объявлены переменные. В языке C# не так уж много возможностей для объявления переменных, пожалуй, меньше, чем в любом другом языке. Открою «страшную» тайну, – здесь вообще нет настоящих глобальных переменных. Их отсутствие не следует считать некоторым недостатком C#, это достоинство языка. Но обо всем по порядку.

Поля

Первая важнейшая роль переменных, – они задают свойства структур, интерфейсов, классов. В языке C# такие переменные называются полями (fields). Структуры, интерфейсы, классы, поля – рассмотрению этих понятий будет посвящена большая часть этой книги, а сейчас сообщу лишь некоторые минимальные сведения, связанные с рассматриваемой темой. Поля объявляются при описании класса (и его частных случаев – интерфейса, структуры). Когда конструктор класса создает очередной объект – экземпляр класса, то он в динамической памяти создает набор полей, определяемых классом, и записывает в них значения, характеризующие свойства данного конкретного экземпляра. Так что каждый объект в памяти можно рассматривать как набор соответствующих полей класса со своими значениями. Время существования и область видимости полей объекта определяется объектом, которому они принадлежат. Объекты в динамической памяти, с которыми не связана ни одна ссылочная переменная, становятся недоступными. Реально они оканчивают свое существование, когда сборщик мусора (garbage collector) выполнит чистку кучи. Для значимых типов, к которым принадлежат экземпляры структур, жизнь оканчивается при завершении блока, в котором они объявлены.




Поделиться с друзьями:


Дата добавления: 2014-12-25; Просмотров: 850; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.007 сек.