Студопедия

КАТЕГОРИИ:


Архитектура-(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. 1 страница




Else

Endregion

Заметьте, в тэге summary нас предупреждают, что этот метод требуется специальному инструментарию – Дизайнеру формы, и он не предназначен для редактирования пользователем; добавление и удаление кода этого метода производится автоматически. Обращаю внимание, после заполнения свойств элементов управления заключительным шагом является их добавление в коллекцию Controls, хранящую все элементы управления. Здесь используется метод AddRange, позволяющий добавить в коллекцию одним махом целый массив элементов управления. Метод Add позволяет добавлять в коллекцию по одному элементу. Позже нам придется добавлять элементы управления в форму программно, динамически изменяя интерфейс формы. Для этого нам придется выполнять те же операции: объявить элемент управления, создать его, используя конструкцию new, задать нужные свойства, и добавить в коллекцию Controls.

В заключение приведу текст обработчика событий командной кнопки. Как задается обработчик того или иного события для элементов управления? Это можно делать по-разному. Есть стандартный способ включения событий. Достаточно выделить нужный элемент в форме, в окне свойств нажать кнопку событий (со значком молнии) и из списка событий выбрать нужное событие и щелкнуть по нему. В данной ситуации все можно сделать проще – двойной щелчок по кнопке включает событие и автоматически строится заготовка обработчика события с нужным именем и параметрами. Вот как она выглядит:

private void button1_Click(object sender, System.EventArgs e)

{

 

}

Нам остается добавить свой текст. Я добавил следующие строки:

string temp;

temp = textBox1.Text;

if (temp == "")

textBox2.Text = "Здравствуй, мир!";

textBox2.Text = "Здравствуй, " + temp + "!";

И вот как это работает:

Рис. 2.5. Форма «Приветствие» в процессе работы

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

Вариант 1

4. Сколько различных типов проектов на C# можно создать в Visual Studio.Net 2003?

q 2;

q 12;

q число их не ограничено;

q 16.

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

q любой проект, входящий в решение, может выступать в роли стартового проекта;

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

q каждый класс содержит одно или несколько пространств имен;

q для каждого решения всегда создается XML-отчет.

6. Решение – это:

q специальный тип проекта;

q специальный компонент проекта;

q основа сборки – модуль, содержащий проекты и другие ресурсы, входящие в сборку;

q стартовый проект на языке C#.

Вариант 2

4. Проект – это:

q модуль, содержащий классы и являющийся частью решения;

q спецификация, отвечающая требованиям CLS;

q компонент пространства имен;

q набор классов, используемых при построении самой Visual Studio.Net.

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

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

q класс Form1 в Windows-проекте по умолчанию является наследником класса Form;

q любой стартовый проект должен содержать точку входа – процедуру Main.

6. Для создания XML-отчета необходимо:

q задать хотя бы один тэг < summary >;

q отчет всегда строится вместе с решением;

q включить соответствующее свойство решения.

Вариант 3

4. Начальный Windows-проект содержит:

q класс Window;

q класс Form;

q класс Form1 – наследника класса Form;

q пространство имен Form.

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

q метод Run – это первый выполняемый метод Windows-проекта;

q процедура Main консольного проекта содержит вызов метода Run;

q класс может выступать в роли цели вызова;

q в каждый момент выполнения проекта существует текущий объект.

6. Если целью вызова является текущий объект, то вызываемый метод должен быть:

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

q динамическим (экземплярным) методом произвольного класса;

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

q статическим методом класса, объектом которого является текущий объект.

 

 

Лекция 3. Система типов языка С#

Общий взгляд. Система типов. Типы-значения и ссылочные типы. Встроенные типы. Сравнение с типами C++. Типы или классы? И типы и классы! Преобразования переменных в объекты и vice versa. Операции «упаковать» и «распаковать». Преобразования типов. Преобразования внутри арифметического типа. Преобразования строкового типа. Класс Convert и его методы. Проверяемые преобразования. Управление проверкой арифметических преобразований.

Ключевые понятия: класс; простой тип; сложный тип; тип, определенный пользователем; статический тип; динамический тип; встроенные типы; типы-значения; значимые типы; ссылочные типы; система типов; фундаментальные типы: логический, символьный, целый, с плавающей точкой, void, указатели, ссылки, массивы, перечисления, структуры, классы; преобразования типов: упаковать; распаковать; неявное преобразование; явное преобразование; проверяемый блок; непроверяемый блок; проверяемое выражение; непроверяемое выражение; отношение наследования; родительский класс; базовый класс; object; потомки; метод; свойства; тэги summary; XML-отчет; согласование по присваиванию; согласование типов; цель; источник; класс Convert; библиотека FCL; исключения; охраняемые блоки; класс Exception.

Общий взгляд

Знакомство с новым языком программирования разумно начинать с изучения системы типов этого языка. Как в нем устроена система типов данных? Какие есть простые типы, как создаются сложные, структурные типы, как определяются собственные типы, динамические типы, как определяются классы.

В первых языках программирования понятие класса отсутствовало – рассматривались только типы данных. При определении типа явно задавалось только множество возможных значений, которые могут принимать переменные этого типа. Например, тип integer задает целые числа в некотором диапазоне. Неявно с типом всегда связывался и набор разрешенных операций. В типизированных языках, к которым относится большинство языков программирования, понятие переменной естественным образом связывалось с типом. Если есть тип Т и переменная x типа Т, то это означало, что переменная может принимать значения из множества, заданного типом, и к ней применимы операции, разрешенные типом.

Классы и объекты впервые появились в программировании в языке Симула 67. Произошло это спустя 10 лет после появления первого алгоритмического языка Фортран. Определение класса наряду с описанием данных содержало четкое определение операций или методов, применимых к данным. Объекты – экземпляры класса, являются обобщением понятия переменной. Сегодня определение класса в C# и других объектных языках, аналогично определению типа в CTS, содержит:

данные, задающие свойства объектов класса;

методы, определяющие поведение объектов класса;

события, которые могут возникать у объектов класса.

Так есть ли различие между этими двумя основополагающими понятиями – типом и классом? На первых порах можно считать, что класс – это хорошо определенный тип данных, объект – хорошо определенная переменная. Понятия фактически являются синонимами и дело вкуса, какое из них употреблять. Встроенные типы, такие как integer или string предпочитают называть по-прежнему типами, а их экземпляры – переменными. Что же касается абстракции данных, описывающей служащих и названной, например, Employee, то естественнее называть ее классом, а ее экземпляры – объектами. Такой взгляд на типы и классы довольно полезен, но он не является полным. Позже при обсуждении классов, наследования постараемся более четко определить принципиальные различия в этих понятиях.

Объектно-ориентированное программирование, доминирующее сегодня, построено на классах и объектах. Тем не менее, понятия типа и переменной все еще остаются центральными при описании языков программирования, что характерно и для языка C#. Заметьте, что и в Framework.Net предпочитают говорить о системе типов, хотя все типы библиотеки FCL являются классами.

Типы данных принято разделять на простые и сложные в зависимости от того, как устроены их данные. У простых (скалярных) типов возможные значения данных едины и неделимы. Сложные типы характеризуются способом структуризации данных, — одно значение сложного типа состоит из множества значений данных, организующих сложный тип.

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

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

Еще одна важная классификация типов – это их деление на значимые и ссылочные типы. Для значимых типов значение переменной (объекта) является неотъемлемой собственностью переменной (точнее собственностью является память, отводимая значению, а само значение может изменяться). Для ссылочных типов значением является ссылка на некоторый объект в памяти, расположенный обычно в динамической памяти – куче. Объект, на который указывает ссылка, может быть разделяемым. Это означает, что несколько ссылочных переменных могут указывать на один и тот же объект и разделять его значения. Значимый тип принято называть развернутым, подчеркивая тем самым, что значение объекта развернуто непосредственно в памяти, отводимой объекту. О ссылочных и значимых типах еще предстоит обстоятельный разговор.

Для большинства процедурных языков, реально используемых программистами, – Паскаль, C++, Java, Visual Basic, C#, система встроенных типов устроена более или менее одинакова. Всегда в языке присутствуют арифметический, логический (булев), символьный типы. Арифметический тип всегда разбивается на подтипы. Всегда допускается организация данных в виде массивов и записей (структур). Внутри арифметического типа всегда допускаются преобразования, всегда есть функции, преобразующие строку в число и обратно. Так что, мой читатель, Ваше знание, по крайней мере, одного из процедурных языков, позволяет построить общую картину системы типов и для языка C#. Отличия будут в нюансах, которые и придают аромат и неповторимость языку.

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

Система типов

Давайте рассмотрим, как устроена система типов в языке C#, но вначале для сравнения приведу классификацию типов в стандарте языка C++.

Стандарт языка C++ включает следующий набор фундаментальных типов:

1. Логический тип (bool).

2. Символьный тип (char).

3. Целые типы. Целые типы могут быть одного из трех размеров – short, int, long, сопровождаемые описателем signed или unsigned, указывающим, на то, как интерпретируется значение, – со знаком или без оного.

4. Типы с плавающей точкой. Эти типы также могут быть одного из трех размеров – float, double, long double.

Кроме того, в языке есть

5. Тип void, используемый для указания на отсутствие информации.

Язык позволяет конструировать типы:

6. Указатели (например, int* – типизированный указатель на переменную типа int).

7. Ссылки (например, double& – типизированная ссылка на переменную типа double).

8. Массивы (например, char[] – массив элементов типа char).

Язык позволяет конструировать пользовательские типы:

9. Перечислимые типы (enum) для представления значений из конкретного множества.

10. Структуры (struct)

11. Классы.

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

Эта схема типов сохранена и в языке C#. Однако здесь на верхнем уровне используется и другая классификация, носящая для C# принципиальный характер. Согласно этой классификации все типы можно разделить на четыре категории:

1. типы -значения (value) или значимые типы.

2. ссылочные (reference).

3. указатели (pointer).

Эта классификация основана на том, где и как хранятся значения типов. Для ссылочного типа значение задает ссылку на область памяти в «куче», где расположен соответствующий объект. Для значимого типа используется прямая адресация, значение хранит собственно данные, и память для них отводится, как правило, в стеке.

В отдельную категорию выделены указатели, что подчеркивает их особую роль в языке. Указатели имеют ограниченную область действия, и могут использоваться только в небезопасных блоках, помеченных как unsafe.

Особый статус имеет и тип void, указывающий на отсутствие какого либо значения.

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

Со структурами дело сложнее. Структуры C# представляют частный случай класса. Объявив свой класс как структуру, программист получает возможность отнести класс к значимым типам, что иногда бывает крайне полезно. Замечу, что в хорошем объектном языке Eiffel программист может любой класс объявить развернутым (expanded), что эквивалентно отнесению к значимому типу. У программиста C# только благодаря структурам появляется возможность управлять отнесением класса к значимым или ссылочным типам. Правда, это не полноценное средство, поскольку на структуры накладываются дополнительные ограничения по сравнению с обычными классами.

Рассмотрим классификацию, согласно которой все типы делятся на встроенные и определенные пользователем. Все встроенные типы C# однозначно отображаются, а фактически совпадают с системными типами каркаса Net Framework, размещенными в пространстве имен System. Поэтому всюду, где можно использовать имя типа, например, – int, с тем же успехом можно использовать и имя – System.Int32.

Замечание: Следует понимать тесную связь и идентичность встроенных типов языка C# и типов каркаса. Какими именами типов следует пользоваться в программных текстах – это спорный вопрос. Джеффри Рихтер в своей известной книге «Программирование на платформе Framework.Net» рекомендует использовать системные имена типов. Другие авторы считают, что следует пользоваться именами типов, принятыми в языке. Возможно, в модулях, предназначенных для межъязыкового взаимодействия, разумны системные имена, в остальных случаях – имена конкретного языка программирования.

В заключение этого раздела приведу таблицу, содержащую описание всех встроенных типов языка C# и их основные характеристики.

 

Таблица 3-1. Встроенные типы языка C#

 

Логический тип
Имя типа Системный тип Значения Размер
bool System.Boolean true, false 8 бит
Арифметические целочисленные типы
Имя типа Системный тип Диапазон Размер
sbyte System.SByte -128 – 128 Знаковое, 8-бит
byte System.Byte 0 – 255 Беззнаковое, 8-бит
short System.Short -32768 –32767 Знаковое, 16-бит
ushort System.UShort 0 – 65535 Беззнаковое, 16-бит
int System.Int32 ≈(-2*109 – 2*109) Знаковое, 32-бит
uint System.UInt32 ≈(0 – 4*10) Беззнаковое, 32-бит
long System.Int64 ≈(-9*1018 – 9*1018) Знаковое, 64-бит
ulong System.UInt64 ≈(0– 18*1018) Беззнаковое, 64-бит
Арифметический тип с плавающей точкой
Имя типа Системный тип Диапазон Точность
float System.Single ±1.5 × 10-45 ±3.4 × 1038 7 цифр
double System.Double ±5.0 × 10-324 ±1.7 × 10308 15-16 цифр
Арифметический тип с фиксированной точкой
Имя типа Системный тип Диапазон Точность
decimal System.Decimal ±1.0 × 10-28 ±7.9 × 1028 28-29 значащих цифр
Символьные типы
Имя типа Системный тип Диапазон Точность
char System.Char U+0000 – U+ffff 16-бит Unicode символ
string System.String Строка из символов Unicode
Объектный тип
Имя типа Системный тип Примечание
object System.Object Прародитель всех встроенных и пользовательских типов
               


Система встроенных типов языка C# не только содержит практически все встроенные типы (за исключением long double) стандарта языка C++, но и перекрывает его разумным образом. В частности тип string является встроенным в язык, что вполне естественно. В области совпадения сохранены имена типов, принятые в C++, что облегчает жизнь тем, кто привык работать на C++, но собирается по тем или иным причинам перейти на язык C#.

Типы или классы? И типы и классы

Язык C# в большей степени, чем язык C++, является языком объектного программирования. В чем это, например, выражается. В языке C# сглажено различие между типом и классом. Все типы – встроенные и пользовательские – одновременно являются классами, связанными отношением наследования. Родительским, базовым классом является класс object. Все же остальные типы или, точнее, классы являются его потомками, наследуя методы этого класса. У класса object есть четыре наследуемых метода:

1. bool Equals(object obj) – проверяет эквивалентность текущего объекта и объекта, переданного в качестве аргумента;

2. System.Type GetType() – возвращает системный тип текущего объекта;

3. string ToString() – возвращает строку, связанную с объектом. Для арифметических типов возвращается значение, преобразованное в строку;

4. int GetHashCode() – служит, как хэш-функция в соответствующих алгоритмах поиска по ключу при хранении данных в хэш-таблицах.

Естественно, что все встроенные типы нужным образом переопределяют методы родителя и добавляют собственные методы и свойства. Учитывая, что и типы, создаваемые пользователем, также являются потомками класса object, то для них необходимо переопределить методы родителя, если предполагается использование этих методов, а реализация родителя, предоставляемая по умолчанию, не обеспечивает нужного эффекта.

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

int x=11;

int v = new Int32();

v = 007;

string s1 = "Agent";

s1 = s1 + v.ToString() +x.ToString();

В этом примере переменная x объявляется, как обычная переменная типа int. В то же время для объявления переменной v того же типа int используется стиль, принятый для объектов. В объявлении используется конструкция new и вызов конструктора класса. В операторе присваивания, записанном в последней строке фрагмента, для обеих переменных вызывается метод ToString, как это делается при работе с объектами. Этот метод, наследуемый от родительского класса object, переопределенный в классе int, возвращает строку с записью целого. Сообщу еще, что класс int не только наследует методы родителя – класса object, – но и дополнительно определяет метод CompareTo, выполняющий сравнение целых, и метод GetTypeCode, возвращающий системный код типа. Для класса int определены также статические методы и поля, о которых расскажу чуть позже.

Так что же такое после этого int, – спросите Вы – тип или класс? Ведь ранее говорилось, что int относится к value типам, следовательно, он хранит в стеке значения своих переменных, в то время как объекты должны задаваться ссылками. С другой стороны, создание экземпляра с помощью конструктора, вызов методов, наконец, существование родительского класса object, – все это указывает на то, что int – это настоящий класс. Правильный ответ состоит в том, что int это и тип и класс. В зависимости от контекста x может восприниматься как переменная типа int или как объект класса int. Это же верно и для всех остальных value типов. Замечу еще, что все значимые типы фактически реализованы как структуры, представляющие частный случай класса.

Остается понять, для чего в языке C# введена такая двойственность. Для int и других значимых типов сохранена концепция типа не только из-за ностальгических воспоминаний о типах. Дело в том, что значимые типы эффективнее в реализации, им проще отводить память, так что соображения эффективности реализации заставили авторов языка сохранить значимые типы. Более важно, что зачастую необходимо оперировать значениями, а не ссылками на них, хотя бы из-за различий в семантике присваивания для переменных ссылочных и значимых типов.

С другой стороны, в определенном контексте крайне полезно рассматривать переменные типа int как настоящие объекты и обращаться с ними как с объектами. В частности полезно иметь возможность создавать и работать со списками, чьи элементы являются разнородными объектами, в том числе и принадлежащими к значимым типам.

Дальнейшие примеры работы с типами и проект Types

Обсуждение особенностей тех или иных конструкций языка невозможно без приведения примеров. Для каждой лекции я строю один или несколько проектов, сохраняя по возможности одну и ту же схему и реально выполняя проекты в среде Visual Studio.Net. Для работы с примерами данной лекции построен консольный проект с именем Types, содержащий два класса: Class1 и Testing. Расскажу чуть подробнее о той схеме, по которой строятся проекты. Класс Class1 строится автоматически при начальном создании проекта. Он содержит процедуру Main – точку входа в проект. В процедуре Main создается объект класса Testing и вызываются методы этого класса, тестирующие те или иные ситуации. Для решения специальных задач помимо всегда создаваемого класса Testing создаются один или несколько классов. Добавление нового класса в проект я осуществляю выбором пункта меню Project/Add Class. В этом случае автоматически создается заготовка для нового класса, содержащая конструктор без параметров. Дальнейшая работа над классом ведется над этой заготовкой. Создаваемые так классы хранятся в проекте в отдельных файлах. Это особенно удобно, если классы используются в разных проектах. Функционально связанную группу классов удобнее хранить в одном файле, что не возбраняется.

Все проекты в книге являются самодокументируемыми. Классы и их методы сопровождаются тэгами <summary>. В результате появляются подсказки при вызове методов и возможность построения XML-отчета, играющего роль спецификации проекта.

Приведу текст класса Class1:

using System;

namespace Types

{

/// <summary>

/// Проект Types содержит примеры, иллюстрирующие работу

/// со встроенными скалярными типами языка С#.

/// Проект содержит классы: Testing, Class1.

/// Класс Class1 содержит точку входа - процедуру Main.

/// </summary>

class Class1

{

/// <summary>

/// Точка входа проекта.

/// В ней создается объект класса Testing

/// и вызываются его методы.

/// </summary>

[STAThread]

static void Main()

{

Testing tm = new Testing();

Console.WriteLine("Testing.Who Test");

tm.WhoTest();

Console.WriteLine("Testing.Back Test");

tm.BackTest();

Console.WriteLine("Testing.OLoad Test");

tm.OLoadTest();

Console.WriteLine("Testing.ToString Test");

tm.ToStringTest();

Console.WriteLine("Testing.FromString Test");

tm.FromStringTest();

Console.WriteLine("Testing.CheckUncheck Test");

tm.CheckUncheckTest();

}

}

}

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

Семантика присваивания.

Рассмотрим присваивание:

x = e;

Чтобы присваивание было допустимым, типы переменной x и выражения e должны быть согласованными. Пусть сущность x согласно объявлению принадлежит классу T. Будем говорить, что тип T основан на классе T и является базовым типом x, так что базовый тип определяется классом объявления. Пусть теперь в рассматриваемом нами присваивании выражение e связано с объектом типа T1.

Определение: тип T1 согласован по присваиванию с базовым типом T переменной x, если класс T1 является потомком класса T.

Присваивание допустимо, если и только если имеет место согласование типов. Так как все классы в языке C# – встроенные и определенные пользователем – по определению являются потомками класса object, то отсюда и следует наш частный случай – переменным класса object можно присваивать выражения любого типа.




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


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


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



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




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