Структуры
Во многих отношениях структуры можно рассматривать как особую разновидность классов.
Для структур можно определять конструкторы, реализовывать интерфейсы. Однако для структур в 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 представляет собой набор строковых значений, состоящих из пар "ключ-значение", в качестве значений которых используется строка.
Рассмотрим пример применения коллекций на примере класса ArrayList.
Для этого воспользуемся рассмотренным ранее классом Client. Очень часто возникает ситуация, при которой необходимо бывает помещать объекты в список или массив для их дальнейшей обработки. Конечно, при этом может быть достаточно тех возможностей, которые предоставляют стандартные массивы C#, рассмотренные ранее.
Однако коллекции, как уже было сказано, обладают более широкими возможностями и, следовательно, их применение предпочтительно по сравнению с массивами.
Задание №3
Для обработки данных о клиентах создадим класс 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 Client this[int pos]
{
get
{
return ((Client)ClientsList[pos]);
}
set
{
ClientsList[pos] = value;
}
}
Как видно, от обычного метода индексатор отличается именем (this), а также наличием квадратных скобок, в которых указывается параметр - номер извлекаемого элемента. С помощью индексатора становится возможным извлечение элемента из коллекции, а также запись элемента в коллекцию под определенным номером:
Response.Write(cl[1].name);
cl[1].name = "Сидоров";
Response.Write(cl[1].name);
Теперь можно организовать обработку элементов массива в цикле. При работе с коллекциями довольно удобной является возможность использования цикла forech. Для реализации такой функциональности при работе с классом Clients необходимо использовать метод GetEnumerator() интерфейса IEnumerator - задать наследование классом Clients интерфейса IEnumerator и реализовать метод, как показано ниже.
public class Clients:IEnumerable
{
public IEnumerator GetEnumerator()
{
return ClientsList.GetEnumerator();
}
}
Пример применения цикла foreach с использованием класса Clients показан ниже.
foreach (Client c in cl)
{
Response.Write("Имя="+c.name+" ");
Response.Write("Паспорт="+c.passport+" ");
Response.Write("Возраст=" + c.age);
Response.Write("</br>");
}
Важные отличия языка C#.
-
Все типы были разделены на значимые и ссылочные.
-
Абсолютно все типы данных C# описываются с помощью классов.
-
Правила передачи параметров в процедуры и функции также претерпели некоторые изменения. В частности, появились ключевые слова in и out, позволяющие четко указывать на направление передачи параметров: в процедуру или из нее.
-
Очень важным компонентом языка C# является возможность использования динамических массивов и расширенные возможности при работе со строками.