Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Базовые технологии платформы .NET.pdf
Скачиваний:
66
Добавлен:
11.05.2015
Размер:
1.73 Mб
Скачать

10. Массивы и класс System.Array

Класс System.Array является базовым классом для любого массива. Любой массив реализует интерфейсы IList и IList<T>, причём IList реализован явно (так как методы Add() и Remove() генерируют исключение в случае коллекции фиксированной длины, которой является массив). В табл. 6 описаны экземплярные элементы любого массива, а табл. 7 содержит статические методы класса Array.

 

 

Таблица 6

 

 

Экземплярные элементы массива

 

 

 

Имя элемента

 

Описание

Rank

 

Свойство для чтения, возвращает размерность массива

Length

 

Свойство для чтения, возвращает общее число элементов массива

LongLength

 

Свойство для чтения, число элементов. Имеет тип long

CopyTo()

 

Метод копирует фрагмент массива в другой массив

GetLength()

 

Метод возвращает число элементов в указанном измерении

GetLowerBound()

 

Метод возвращает нижнюю границу для указанного измерения

GetUpperBound()

 

Метод возвращает верхнюю границу для указанного измерения

GetValue()

 

Метод возвращает значение элемента с указанными индексами

SetValue()

 

Метод устанавливает значение элемента с указанными индексами

 

 

Таблица 7

 

 

Статические методы класса System.Array

 

 

 

Имя метода

 

Описание

Sort()

 

Сортирует массив, переданный в качестве аргумента (возможно, с

 

применением собственного объекта для сравнения элементов)

 

 

BinarySearch()

 

Поиска элемента в отсортированном массиве

IndexOf()

 

Возвращает индекс первого вхождения своего аргумента в одномер-

 

ный массив (фрагмент массива) или –1, если элемента в массиве нет

 

 

LastIndexOf()

 

Возвращает индекс последнего вхождения аргумента в одномерный

 

массив (фрагмент массива) или –1, если элемента в массиве нет

 

 

Exists()

 

Определяет, содержит ли массив хотя бы один элемент, удовлетворя-

 

ющий предикату, который задан аргументом метода

 

 

Find()

 

Возвращает первый элемент, удовлетворяющий предикату, который

 

задан аргументом метода

 

 

FindLast()

 

Возвращает первый элемент с конца массива, удовлетворяющий пре-

 

дикату, который задан аргументом метода

 

 

FindAll()

 

Возвращает все элементы, удовлетворяющие предикату, который задан

 

аргументом метода

 

 

FindIndex()

 

Возвращает индекс первого вхождения элемента, удовлетворяющего

 

предикату, заданному как аргумент метода

 

 

FindLastIndex()

 

Возвращает индекс последнего вхождения элемента, удовлетворяюще-

 

го предикату, заданному как аргумент метода

 

 

ConvertAll()

 

Конвертирует массив одного типа в массив другого типа

ForEach()

 

Выполняет указанное действие для всех элементов массива

TrueForAll()

 

Возвращает true, если заданный предикат верен для всех элементов

Clear()

 

Устанавливает для массива или его части значение по умолчанию для

 

типа элементов

 

 

37

Reverse()

Меняет порядок элементов в одномерном массиве или его части на

противоположный

 

AsReadOnly()

Создаёт на основе массива коллекцию, не допускающую модификации

своих элементов (read-only collection)

 

CreateInstance()

Создаёт экземпляр массива любого типа, размерности и длины

Copy()

Копирует раздел одного массива в другой массив, выполняя приведе-

ние типов

 

ConstrainedCopy()

Метод подобен Copy(), но если приведение типов для элементов не-

удачно, выполняется отмена операции копирования

Resize()

Позволяет изменить размер массива

Рассмотрим несколько примеров использования методов массива. В первом примере создадим массив и выполним работу с его элементами, не применяя традиционный синтаксис C#.

Array a = Array.CreateInstance(typeof

(string),

2);

// тип, длина

a.SetValue("hi", 0);

// a[0]

=

"hi";

 

a.SetValue("there", 1);

//

a[1]

= "there";

string s = (string) a.GetValue(0);

//

s = a[0];

 

Метод CreateInstance() может создать массив любой размерности с указанным диапазоном изменения индексов:

// b – это массив int[-5..4,

100..119]

 

var b = Array.CreateInstance(typeof (int),

// тип элемента

 

new[] {10, 20},

// длины размерностей

 

new[] {-5, 100}); // нижние границы

b.SetValue(25, -3, 110);

 

 

int x = (int) b.GetValue(-2,

115);

 

Группа статических методов класса Array позволяет выполнить сортировку и поиск данных в массиве. Методы поиска могут использовать заданные предикаты, а сортировка – выполняться по заданному критерию сравнения.

int[] a = {10, 3, 5, -7, 0, 20,

10, 4};

// исходный массив

int b = Array.Find(a, x => x > 6);

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

int[] c = Array.FindAll(a, x => x > 6);

// поиск всех элементов

Array.ForEach(c, Console.WriteLine);

//

действие над элементами

bool flag = Array.TrueForAll(a,

x => x > 0);

// проверка условия

Array.Sort(a, (x, y) => x == y ? 0 : x > y ?

-1 : 1); // сортировка

int pos = Array.BinarySearch(a,

3);

 

// двоичный поиск

Массивы допускают копирование элементов и изменение размера:

int[] a = {10, 3, 5, -7, 0, 20, 10, 4}; int[] b = new int[a.Length];

long[] c = new long[a.Length]; a.CopyTo(b, 0);

Array.Copy(a, c, a.Length); Array.Resize(ref a, 40);

38

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

int[] a

= {10, 3, 5, -7, 0, 20, 10, 4};

 

int[] b

= new int[a.Length];

 

 

Buffer.BlockCopy(a, 3, b, 5, 10);

//

смещение задано в байтах

11. Типы для работы с коллекциями-списками

Рассмотрим типы из базовой библиотеки платформы .NET, применяемые при работе с коллекциями со списковой семантикой.

Класс List<T> из пространства имён System.Collections.Generic – основ-

ной класс для представления наборов, которые допускают динамическое добавление элементов1. Для хранения данных набора используется внутренний массив. Класс List<T> реализует интерфейсы IList<T> и IList. В табл. 8 представлено описание public-элементов класса List<T>.

Таблица 8

 

 

Элементы класса List<T>

 

 

 

Элемент

 

Описание

Добавление и удаление элементов

Add()

 

Добавление одного элемента

AddRange()

 

Добавление набора элементов

Insert()

 

Вставка элемента в заданную позицию

InsertRange()

 

Вставка набора элементов

Remove()

 

Удаление элемента

RemoveAt()

 

Удаление элемента на указанной позиции со сдвигом остальных

RemoveRange()

 

Удаление диапазона элементов

RemoveAll()

 

Удаление всех элементов, удовлетворяющих заданному предикату

Индексирование элементов

this[int index]

 

Основной индексатор

GetRange()

 

Получение подсписка

GetEnumerator()

 

Получение перечислителя

Поиск и сортировка

 

BinarySearch()

 

Поиск элемента в упорядоченном наборе

IndexOf()

 

Индекс первого вхождения своего аргумента в набор

LastIndexOf()

 

Индекс последнего вхождения своего аргумента в набор

Contains()

 

Проверка, содержится ли указанный элемент в наборе

Exists()

 

Проверка, содержит ли набор элемент, удовлетворяющий предикату

Find()

 

Возвращает первый элемент, удовлетворяющий предикату, который за-

 

дан как аргумент метода

 

 

FindLast()

 

Возвращает первый элемент с конца набора, удовлетворяющий предика-

 

ту, который задан как аргумент метода

 

 

FindAll()

 

Возвращает все элементы набора, удовлетворяющие предикату

FindIndex()

 

Возвращает индекс первого вхождения элемента, удовлетворяющего

 

предикату, который задан как аргумент метода

 

 

1 В пространстве имён System.Collections имеется слаботипизированный аналог класса

List<T> – класс ArrayList.

39

FindLastIndex()

Возвращает индекс последнего вхождения элемента, удовлетворяющего

предикату, который задан как аргумент метода

 

TrueForAll()

Возвращает true, если заданный предикат верен для всех элементов

Sort()

Сортировка набора (возможно, с применением собственного объекта для

сравнения элементов)

 

Экспорт и конвертирование элементов

ToArray()

Преобразование набора в массив

CopyTo()

Копирование набора или его части в массив

AsReadOnly()

Преобразование набора в коллекцию только для чтения

ConvertAll()

Конвертирование набора одно типа в набор другого типа

Другие методы и свойства

Count

Количество элементов в наборе

Capacity

Ёмкость набора

TrimExcess()

Усечение размера внутреннего массива до необходимой минимальной

величины

 

Clear()

Очистка списка (удаление всех элементов)

Reverse()

Изменение порядка элементов на противоположный

ForEach()

Выполняет указанное действие для всех элементов списка

Класс List<T> имеет три конструктора. Первый из них – обычный конструктор без параметров. Второй конструктор позволяет создать набор на основе коллекции – производится копирование элементов коллекции в список. Третий конструктор принимает в качестве аргумента начальную ёмкость набора. Ёмкость набора (capacity) – это количество элементов набора, которое он способен содержать без увеличения размера внутреннего массива.

Следующий код демонстрирует использование некоторых свойств и методов класса List<T>. Обратите внимание, что для добавления элементов в созданный набор применяется возможность инициализации классов-коллекций.

List<string> words = new List<string> {"melon", "avocado"}; words.AddRange(new[] {"banana", "plum"});

words.Insert(0, "lemon");

words.InsertRange(0, new[] {"peach", "apple"}); words.Remove("melon");

words.RemoveAt(3);

words.RemoveAll(s => s.StartsWith("a")); List<string> subset = words.GetRange(1, 2); string[] wordsArray = words.ToArray();

List<int> lengths = words.ConvertAll<int>(s => s.Length);

На примере List<T> рассмотрим особенность, присущую использованию коллекций в языке C#. Если коллекция хранит структуры, то C# не позволяет изменить части структуры при помощи индексатора коллекции (так как индексатор является функцией, возвращающей копию элемента коллекции):

public struct Student

{

public string Name { get; set; }

}

40

LinkedListNode<T>.

var list = new

List<Student> {new Student {Name =

"Ivanov"}};

list[0].Name =

"Petrov";

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

 

Класс LinkedList<T> служит для представления двусвязного списка. Такой список позволяет осуществлять вставку и удаление элемента без сдвига остальных элементов. Однако доступ к элементу по индексу требует прохода по спис-

ку. LinkedList<T> реализует интерфейсы ICollection и ICollection<T>. Каж-

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

public sealed class LinkedListNode<T>

{

public LinkedList<T> List { get; } public LinkedListNode<T> Next { get; }

public LinkedListNode<T> Previous { get; } public T Value { get; set; }

}

При добавлении элемента можно указать, чтобы он помещался в начало списка, или в конец списка, или относительно существующего в списке элемента. Для этого класс LinkedList<T> содержит специальные методы:

public void AddFirst(LinkedListNode<T> node); public LinkedListNode<T> AddFirst(T value);

public void AddLast(LinkedListNode<T> node); public LinkedListNode<T> AddLast(T value);

public void AddAfter(LinkedListNode<T> node, LinkedListNode<T> newNode);

public LinkedListNode<T> AddAfter(LinkedListNode<T> node, T value);

public void AddBefore(LinkedListNode<T> node, LinkedListNode<T> newNode);

public LinkedListNode<T> AddBefore(LinkedListNode<T> node, T value);

Аналогичные методы существуют и для удаления элементов списка:

public void RemoveFirst(); public void RemoveLast(); public bool Remove(T value);

public void Remove(LinkedListNode<T> node);

Класс LinkedList<T> содержит свойства для числа элементов, для указания на первый и последний элемент. Имеются методы для поиска элементов.

Ниже приведён пример использования LinkedList<T>.

var tune = new LinkedList<string>();

 

tune.AddFirst("do");

// do

41

tune.AddLast("so");

// do - so

tune.AddAfter(tune.First, "re");

// do - reso

tune.AddAfter(tune.First.Next, "mi");

// do - re - miso

tune.AddBefore(tune.Last, "fa");

// do - re - mi - faso

tune.RemoveFirst();

// re - mi - fa - so

tune.RemoveLast();

// re - mi - fa

var miNode = tune.Find("mi");

 

tune.Remove(miNode);

// re - fa

tune.AddFirst(miNode);

// mi - re - fa

Классы Queue<T> и Stack<T> реализуют структуры данных «очередь» и «стек» на основе массива1. Конструкторы этих классов, как и конструкторы класса List<T>, позволяют создать объект на основе другой коллекции, а также указать значение для ёмкости (но ёмкость не доступна в виде отдельного свойства). Элементы классов вполне предсказуемы и описаны в табл. 9 и табл. 10.

Таблица 9

 

Элементы класса Queue<T>

 

 

Элемент

Описание

Clear()

Очистка очереди (удаление всех элементов)

Contains()

Проверка, содержится ли указанный элемент в очереди

CopyTo()

Копирование очереди в массив

Count

Количество элементов (свойство только для чтения)

Dequeue()

Извлечение элемента из очереди

Enqueue()

Помещение элемента в очередь

GetEnumerator()

Получение перечислителя

Peek()

Чтение очередного элемента без его удаления из очереди

ToArray()

Преобразование очереди в массив

TrimExcess()

Усечение размера внутреннего массива до необходимой минимальной

величины

 

 

Таблица 10

 

Элементы класса Stack<T>

 

 

Элемент

Описание

Clear()

Очистка стека (удаление всех элементов)

Contains()

Проверка, содержится ли указанный элемент в стеке

CopyTo()

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

Count

Количество элементов (свойство только для чтения)

GetEnumerator()

Получение перечислителя

Peek()

Чтение очередного элемента без его удаления из стека

Pop()

Извлечение элемента из стека

Push()

Помещение элемента в стек

ToArray()

Преобразование стека в массив

TrimExcess()

Усечение размера внутреннего массива до необходимой минимальной

величины

 

1 В пространстве имён System.Collections имеются слаботипизированные аналоги классов

Queue<T> и Stack<T> – классы Queue и Stack.

42