Основы языка C#
Структуры
Во многих отношениях структуры можно рассматривать как особую разновидность классов.
Для структур можно определять конструкторы, реализовывать интерфейсы. Однако для структур в C# не существует базового класса, поэтому все структуры являются производными от типа ValueType.
Простейший пример структуры можно представить так:
public struct Employee { public string name; public string type; public int deptID; }
Использование структуры возможно следующим образом. Сначала ее необходимо создать. В момент создания структуры для нее выделяется память в области стека. В дальнейшем к элементам структуры возможно обращение путем указания имени структуры и имени элемента, разделенных точкой:
Employee Alex; Alex.name = "Alex"; Alex.type = "manager"; Alex.deptID = 2310;
В реальной системе для более удобного использования структур целесообразно определить конструктор или несколько конструкторов. При этом необходимо помнить, что в структурах невозможно переопределить конструктор по умолчанию (без параметров). Все определенные в структуре конструкторы должны принимать параметры. Ниже представлен пример конструктора структуры.
public Employee(int DeptID, string Name, string EmpType) { deptID = DeptID; type = EmpType; name = Name; }
Использование конструктора выглядит следующим образом:
Employee Nick=new Employee(278,"Nick","worker");
Как видно, для вызова конструктора структуры необходимо использовать ключевое слово new.
Аналогичным образом становится возможным создание и использование методов структур.
Коллекции
Массивы - это удобное средство организации хранения и упорядочивания информации. Однако при работе с массивами практически всегда возникают задачи, которые связаны с обработкой данных, содержащихся в них. В современном программировании очень часто элементами массива являются объекты, над которыми необходимо выполнять различные действия. В силу особенностей коллекций, а также учитывая тот факт, что упор при изложении данного материала был сделан на использование коллекций для хранения именно объектов, раздел, посвященный коллекциям, расположен после раздела, посвященного классам и структурам.
Ранее был рассмотрен класс Array, в котором реализован целый набор часто используемых операций над элементами массива, таких как сортировка, клонирование, перечисления и расстановка элементов в обратном порядке. Тем не менее при работе с массивами возникает и целый ряд других задач. Решением этих задач и занимаются коллекции, позволяющие организовывать элементы специальным образом и производить впоследствии над ними определенный набор операций.
Все определенные в .NET Framework коллекции расположены в пространстве имен System.Collections. Наиболее часто используемые коллекции этого пространства имен представлены ниже.
ArrayList | Массив объектов, динамически изменяющий свой размер. |
Hashtable | Набор взаимосвязанных ключей и значений, основанных на хэш-коде ключа. |
Queue | Стандартная очередь, реализованная по принципу "первым вошел, первым вышел" (FIFO – First In First Out). |
SortedList | Представляет класс, элементами которого могут быть пары "ключ-значение", отсортированные по значению ключа и предоставляющие доступ к элементам по их порядковому номеру (индексу). |
Stack | Очередь, реализованная по принципу "последним вошел, первым вышел" (LIFO – Last In First Out). |
В пространстве имен System.Collections.Specialized расположены классы, предназначенные для использования в специальных случаях. Так, класс StringCollection представляет набор строк. Класс StringDictionary представляет собой набор строковых значений, состоящих из пар "ключ-значение", в качестве значений которых используется строка.
В данной лекции будут рассмотрены общие вопросы применения коллекций. Для более детального изучения их особенностей и возможностей рекомендуется ознакомиться с разделом "Интерфейсы", а также использовать дополнительную литературу и справочную систему MSDN.
Рассмотрим пример применения коллекций на примере класса ArrayList. Для этого воспользуемся рассмотренным ранее классом Client. Очень часто возникает ситуация, при которой необходимо бывает помещать объекты в список или массив для их дальнейшей обработки. Конечно, при этом может быть достаточно тех возможностей, которые предоставляют стандартные массивы C#, рассмотренные ранее. Однако коллекции, как уже было сказано, обладают более широкими возможностями и, следовательно, их применение предпочтительно по сравнению с массивами. Так, для обработки данных о клиентах создадим класс Clients, предназначенный для хранения списка клиентов и его обработки. При этом необходимо учесть, что класс Clients должен обеспечивать возможность добавления, удаления и нумерации элементов (клиентов). Для реализации этой функциональности необходимо использовать класс ArrayList в качестве вложенного в класс Clients. Таким образом, нам необходимо определить в данном классе элемент, позволяющий вести список клиентов, а также реализовать набор открытых методов, которые будут передавать вызовы на выполнение различных действий внутреннему классу, производному от ArrayList. Пример исходного кода класса Clients приведен ниже.
public class Clients { private ArrayList ClientsList; public Clients() { ClientsList=new ArrayList(); } public int ClientsCount { get { return ClientsList.Count; } } public void AddClient(Client c) { ClientsList.Add(c); } public void RemoveClient(int ClientToRemove) { ClientsList.RemoveAt(ClientToRemove); } public Client GetClient(int ClientID) { return (Client)ClientsList[ClientID]; } }
Использование такого класса представляется очень простым:
Clients cl=new Clients(); cl.AddClient(new Client("Сидоров","9002",new DateTime(1980,12,21))); cl.AddClient(new Client("Петров","9004",new DateTime(1975,03,15)));
Теперь становится возможным обращение к любому классу Client, помещенному в коллекцию Clients посредством метода GetClient:
Client MyClient = cl.GetClient(1); Response.Write(MyClient.name);
Результатом работы этого фрагмента программы будет строка "Петров".
Тем не менее существует несколько неудобств от использования класса Clients в его нынешней реализации. Во-первых, более привычным обращением к элементу массива либо списка в языке C# является использование индексаторов, обозначаемых в виде квадратных скобок. Для реализации этой возможности в классе Clients необходимо создать индексатор:
public Clients this[int pos] { get { return ((Clients)ClientsList[pos]); } set { ClientsList[pos] = value; } }
Как видно, от обычного метода индексатор отличается именем ( this ), а также наличием квадратных скобок, в которых указывается параметр - номер извлекаемого элемента. С помощью индексатора становится возможным извлечение элемента из коллекции, а также запись элемента в коллекцию под определенным номером:
Response.Write(cl[1].name); cl[1].name = "Сидоров"; Response.Write(cl[1].name);
Теперь можно организовать обработку элементов массива в цикле. При работе с коллекциями довольно удобной является возможность использования цикла foreach. Для реализации такой функциональности при работе с классом Clients необходимо использовать метод GetEnumerator() интерфейса IEnumerator - задать наследование классом Clients интерфейса IEnumerator и реализовать метод, как показано ниже.
public class Clients:IEnumerable { public IEnumerator GetEnumerator() { return ClientsList.GetEnumerator(); } }
Пример применения цикла foreach с использованием класса Clients показан ниже.
foreach (Clients c in cl) { Response.Write("Имя="+c.name+" "); Response.Write("Паспорт="+c.passport+" "); Response.Write("Возраст=" + c.age); Response.Write("</br>"); }
Краткие итоги
Язык C# является наследником C++, перенимая основные элементы синтаксиса и базовую систему типов. При этом в него были введены некоторые элементы, свойственные другим языкам программирования, таким, например, как Visual Basic. В C# существует достаточно много нововведений, направленных на упрощение работы с ним и на повышение гибкости его использования.
Важные отличия произошли в системе типов языка C#. Все типы были разделены на значимые и ссылочные. Причем в среде .NET Framework были определены правила использования тем или иным типом доступной оперативной памяти, которые должен учитывать программист в процессе разработки программы.
Важнейшей характеристикой языка является тот факт, что он является полностью объектно-ориентированным. Это означает, что абсолютно все типы данных описываются с помощью классов. Основу синтаксиса описания классов C# также позаимствовал у C++. Однако и здесь были введены новые элементы, которые способствуют решению части неудобств, возникающих при использовании C++. Правила передачи параметров в процедуры и функции также претерпели некоторые изменения. В частности, появились ключевые слова in и out, позволяющие четко указывать на направление передачи параметров: в процедуру или из нее.
Очень важным компонентом языка является возможность использования динамических массивов и расширенные возможности при работе со строками.