Массив как поле класса c
Перейти к содержимому

Массив как поле класса c

  • автор:

Массив как поле класса c

Все массивы в C# построены на основе класса Array из пространства имен System. Этот класс определяет ряд свойств и методов, которые мы можем использовать при работе с массивами. Основные свойства и методы:

  • Свойство Length возвращает длину массива
  • Свойство Rank возвращает размерность массива
  • int BinarySearch (Array array, object? value) выполняет бинарный поиск в отсортированном массиве и возвращает индекс найденного элемента
  • void Clear (Array array) очищает массив, устанавливая для всех его элементов значение по умолчанию
  • void Copy (Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length) копирует из массива sourceArray начиная с индекс sourceIndex length элементов в массив destinationArray начиная с индекса destinationIndex
  • bool Exists (T[] array, Predicate match) проверяет, содержит ли массив array элементы, которые удовлеворяют условию делегата match
  • void Fill (T[] array, T value) заполняет массив array значением value
  • T? Find (T[] array, Predicate match) находит первый элемент, который удовлеворяет определенному условию из делегата match. Если элемент не найден, то возвращается null
  • T? FindLast (T[] array, Predicate match) находит последний элемент, который удовлеворяет определенному условию из делегата match. Если элемент не найден, то возвращается null
  • int FindIndex (T[] array, Predicate match) возвращает индекс первого вхождения элемента, который удовлеворяет определенному условию делегата match
  • int FindLastIndex (T[] array, Predicate match) возвращает индекс последнего вхождения элемента, который удовлеворяет определенному условию
  • T[] FindAll (T[] array, Predicate match) возвращает все элементы в виде массива, которые удовлеворяет определенному условию из делегата match
  • int IndexOf (Array array, object? value) возвращает индекс первого вхождения элемента в массив
  • int LastIndexOf (Array array, object? value) возвращает индекс последнего вхождения элемента в массив
  • void Resize (ref T[]? array, int newSize) изменяет размер одномерного массива
  • void Reverse (Array array) располагает элементы массива в обратном порядке
  • void Sort (Array array) сортирует элементы одномерного массива

Разберем самые используемые методы.

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

var people = new string[] < "Tom", "Sam", "Bob", "Kate", "Tom", "Alice" >; // находим индекс элемента "Bob" int bobIndex = Array.BinarySearch(people, "Bob"); // находим индекс первого элемента "Tom" int tomFirstIndex = Array.IndexOf(people, "Tom"); // находим индекс последнего элемента "Tom" int tomLastIndex = Array.LastIndexOf(people, "Tom"); // находим индекс первого элемента, у которого длина строки больше 3 int lengthFirstIndex = Array.FindIndex(people, person => person.Length > 3); // находим индекс последнего элемента, у которого длина строки больше 3 int lengthLastIndex = Array.FindLastIndex(people, person => person.Length > 3); Console.WriteLine($"bobIndex: "); // 2 Console.WriteLine($"tomFirstIndex: "); // 0 Console.WriteLine($"tomLastIndex: "); // 4 Console.WriteLine($"lengthFirstIndex: "); // 3 Console.WriteLine($"lengthLastIndex: "); // 5

Если элемент не найден в массиве, то методы возвращают -1.

Поиск элемента по условию

var people = new string[] < "Tom", "Sam", "Bob", "Kate", "Tom", "Alice" >; // находим первый и последний элементы // где длина строки больше 3 символов string? first = Array.Find(people, person => person.Length > 3); Console.WriteLine(first); // Kate string? last = Array.FindLast(people, person => person.Length > 3); Console.WriteLine(last); // Alice // находим элементы, у которых длина строки равна 3 string[] group = Array.FindAll(people, person => person.Length == 3); foreach (var person in group) Console.WriteLine(person); // Tom Sam Bob Tom

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

Например, изменим порядок элементов:

var people = new string[] < "Tom", "Sam", "Bob", "Kate", "Tom", "Alice" >; Array.Reverse(people); foreach (var person in people) Console.Write($" "); // "Alice", "Tom", "Kate", "Bob", "Sam", "Tom"

Также можно изменить порядок только части элементов:

var people = new string[] < "Tom", "Sam", "Bob", "Kate", "Tom", "Alice" >; // изменяем порядок 3 элементов начиная c индекса 1 Array.Reverse(people, 1, 3); foreach (var person in people) Console.Write($" "); // "Tom", "Kate", "Bob", "Sam", "Tom", "Alice"

В данном случае изменяем порядок только 3 элементов начиная c индекса 1.

Изменение размера массива

Для изменения размера массива применяется метод Resize. Его первый параметр — изменяемый массив, а второй параметр — количество элементов, которые должны быть в массиве. Если второй параметр меньше длины массива, то массив усекается. Если значение параметра, наоборот, больше, то массив дополняется дополнительными элементами, которые имеют значение по умолчанию. Причем первый параметр передается по ссылке:

var people = new string[] < "Tom", "Sam", "Bob", "Kate", "Tom", "Alice" >; // уменьшим массив до 4 элементов Array.Resize(ref people, 4); foreach (var person in people) Console.Write($" "); // "Tom", "Sam", "Bob", "Kate"

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

Метод Copy копирует часть одного массива в другой:

var people = new string[] < "Tom", "Sam", "Bob", "Kate", "Tom", "Alice" >; var employees = new string[3]; // копируем 3 элемента из массива people c индекса 1 // и вставляем их в массив employees начиная с индекса 0 Array.Copy(people,1, employees,0, 3); foreach (var person in employees) Console.Write($" "); // Sam Bob Kate

В данном случае копируем 3 элемента из массива people начиная c индекса 1 и вставляем их в массив employees начиная с индекса 0.

Сортировка массива

Отсортируем массив с помощью метода Sort() :

var people = new string[] < "Tom", "Sam", "Bob", "Kate", "Tom", "Alice" >; Array.Sort(people); foreach (var person in people) Console.Write($" "); // Alice Bob Kate Sam Tom Tom

Этот метод имеет много перегрузок. Например, одна из версий позволяет отсортировать только часть массива:

var people = new string[] < "Tom", "Sam", "Bob", "Kate", "Tom", "Alice" >; // сортируем с 1 индекса 3 элемента Array.Sort(people, 1, 3); foreach (var person in people) Console.Write($" "); // Tom Bob Kate Sam Tom Alice

Массив как поле класса c

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

тип_переменной[] название_массива;

Например, определим массив целых чисел:

int[] numbers;

После определения переменной массива мы можем присвоить ей определенное значение:

int[] nums = new int[4];

Здесь вначале мы объявили массив nums, который будет хранить данные типа int . Далее используя операцию new , мы выделили память для 4 элементов массива: new int[4] . Число 4 еще называется длиной массива . При таком определении все элементы получают значение по умолчанию, которое предусмотренно для их типа. Для типа int значение по умолчанию — 0.

Также мы сразу можем указать значения для этих элементов:

int[] nums2 = new int[4] < 1, 2, 3, 5 >; int[] nums3 = new int[] < 1, 2, 3, 5 >; int[] nums4 = new[] < 1, 2, 3, 5 >; int[] nums5 = < 1, 2, 3, 5 >;

Все перечисленные выше способы будут равноценны.

Подобным образом можно определять массивы и других типов, например, массив значений типа string :

string[] people = < "Tom", "Sam", "Bob" >;

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

Для обращения к элементам массива используются индексы . Индекс представляет номер элемента в массиве, при этом нумерация начинается с нуля, поэтому индекс первого элемента будет равен 0, индекс четвертого элемента — 3.

Используя индексы, мы можем получить элементы массива:

int[] numbers = < 1, 2, 3, 5 >; // получение элемента массива Console.WriteLine(numbers[3]); // 5 // получение элемента массива в переменную var n = numbers[1]; // 2 Console.WriteLine(n); // 2

Также мы можем изменить элемент массива по индексу:

int[] numbers = < 1, 2, 3, 5 >; // изменим второй элемент массива numbers[1] = 505; Console.WriteLine(numbers[1]); // 505

И так как у нас массив определен только для 4 элементов, то мы не можем обратиться, например, к шестому элементу. Если мы так попытаемся сделать, то мы получим ошибку во время выполнения:

int[] numbers = < 1, 2, 3, 5 >; Console.WriteLine(numbers[6]); // ! Ошибка - в массиве только 4 элемента

Свойство Length и длина массива

каждый массив имеет свойство Length , которое хранит длину массива. Например, получим длину выше созданного массива numbers:

int[] numbers = < 1, 2, 3, 5 >; Console.WriteLine(numbers.Length); // 4

Для получения длины массива после названия массива через точку указывается свойство Length : numbers.Length .

Получение элементов с конца массива

Благодаря наличию свойства Length , мы можем вычислить индекс последнего элемента массива — это длина массива — 1. Например, если длина массива — 4 (то есть массив имеет 4 элемента), то индекс последнего элемента будет равен 3. И, используя свойство Length , мы можем легко получить элементы с конца массива:

int[] numbers = < 1, 2, 3, 5>; Console.WriteLine(numbers[numbers.Length - 1]); // 5 - первый с конца или последний элемент Console.WriteLine(numbers[numbers.Length - 2]); // 3 - второй с конца или предпоследний элемент Console.WriteLine(numbers[numbers.Length - 3]); // 2 - третий элемент с конца

Однако при подобном подходе выражения типа numbers.Length — 1 , смысл которых состоит в том, чтобы получить какой-то определенный элемент с конца массива, утяжеляют код. И, начиная, с версии C# 8.0 в язык был добавлен специальный оператор ^ , с помощью которого можно задать индекс относительно конца коллекции.

Перепишем предыдущий пример, применяя оператор ^ :

int[] numbers = < 1, 2, 3, 5>; Console.WriteLine(numbers[^1]); // 5 - первый с конца или последний элемент Console.WriteLine(numbers[^2]); // 3 - второй с конца или предпоследний элемент Console.WriteLine(numbers[^3]); // 2 - третий элемент с конца

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

Для перебора массивов мы можем использовать различные типы циклов. Например, цикл foreach :

int[] numbers = < 1, 2, 3, 4, 5 >; foreach (int i in numbers)

Здесь в качестве контейнера выступает массив данных типа int . Поэтому мы объявляем переменную с типом int

Подобные действия мы можем сделать и с помощью цикл for:

int[] numbers = < 1, 2, 3, 4, 5 >; for (int i = 0; i

В то же время цикл for более гибкий по сравнению с foreach . Если foreach последовательно извлекает элементы контейнера и только для чтения, то в цикле for мы можем перескакивать на несколько элементов вперед в зависимости от приращения счетчика, а также можем изменять элементы:

int[] numbers = < 1, 2, 3, 4, 5 >; for (int i = 0; i

Также можно использовать и другие виды циклов, например, while :

int[] numbers = < 1, 2, 3, 4, 5 >; int i = 0; while(i

Многомерные массивы

Массивы характеризуются таким понятием как ранг или количество измерений. Выше мы рассматривали массивы, которые имеют одно измерение (то есть их ранг равен 1) — такие массивы можно представлять в виде ряда (строки или столбца) элемента. Но массивы также бывают многомерными. У таких массивов количество измерений (то есть ранг) больше 1.

Массивы которые имеют два измерения (ранг равен 2) называют двухмерными. Например, создадим одномерный и двухмерный массивы, которые имеют одинаковые элементы:

int[] nums1 = new int[] < 0, 1, 2, 3, 4, 5 >; int[,] nums2 = < < 0, 1, 2 >, < 3, 4, 5 >>;

Визуально оба массива можно представить следующим образом:

Массивы

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

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

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

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 < class Program < static void Main(string[] args) < // Объявляем массив int[] myArr = new int[5]; // Инициализируем каждый элемент массива вручную myArr[0] = 100; myArr[1] = 23; myArr[2] = 25; myArr[3] = 31; myArr[4] = 1; foreach (int i in myArr) Console.WriteLine(i); Console.ReadLine(); >> >

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

Инициализация массива

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

// Синтаксис инициализации массива с использованием // ключевого слова new int[] myArr = new int[] ; // Синтаксис инициализации массива без использования // ключевого слова new string[] info = < "Фамилия", "Имя", "Отчество" >; // Используем ключевое слово new и желаемый размер char[] symbol = new char[4] < 'X','Y','Z','M' >;

Обратите внимание, что в случае применения синтаксиса с фигурными скобками размер массива указывать не требуется (как видно на примере создания переменной myArr), поскольку этот размер автоматически вычисляется на основе количества элементов внутри фигурных скобок. Кроме того, применять ключевое слово new не обязательно (как при создании массива info).

Неявно типизированные массивы

Ключевое слово var позволяет определить переменную так, чтобы лежащий в ее основе тип выводился компилятором. Аналогичным образом можно также определять неявно типизированные локальные массивы. С использованием такого подхода можно определить новую переменную массива без указания типа элементов, содержащихся в массиве. Давайте рассмотрим пример:

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 < class Program < static void Main(string[] args) < var arr1 = new[] < 1, 2, 3 >; Console.WriteLine("Тип массива arr1 - ",arr1.GetType()); var arr2 = new[] < "One", "Two", "Three" >; Console.WriteLine("Тип массива arr2 - ",arr2.GetType()); Console.ReadLine(); > > > 

Неявно типизированные массивы

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

Определение массива объектов

В большинстве случаев при определении массива тип элемента, содержащегося в массиве, указывается явно. Хотя на первый взгляд это выглядит довольно понятно, существует одна важная особенность. В основе каждого типа в системе типов .NET (в том числе фундаментальных типов данных) в конечном итоге лежит базовый класс System.Object. В результате получается, что в случае определения массива объектов находящиеся внутри него элементы могут представлять собой что угодно:

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 < class Program < static void Main(string[] args) < // Объявляем и инициализируем массив объектов object[] arrByObject = < true, 10, "Привет", 13.7m >; // Выведем в консоль тип каждого члена массива foreach (object me in arrByObject) Console.WriteLine("Тип - ",me,me.GetType()); Console.ReadLine(); > > >

Массив объектов

Свойство Length

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

Когда запрашивается длина многомерного массива, то возвращается общее число элементов, из которых может состоять массив. Благодаря наличию у массивов свойства Length операции с массивами во многих алгоритмах становятся более простыми, а значит, и более надежными. Давайте рассмотрим пример использования свойства Length:

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 < class Program < static void Main(string[] args) < int[] myArr = < 1, 2, 3, 4 >; for (int i = 0; i < myArr.Length; i++) Console.WriteLine(myArr[i]); Console.ReadLine(); >> >

Массив как поле класса c

Шаг 125.
Язык программирования C#. Начала
Свойства и индексаторы. Использование свойств (и еще продолжение)

На этом шаге мы рассмотрим пример использования нескольких свойств в одном классе .

Еще одна программа, иллюстрирующая использование сразу нескольких свойств в одном классе, представлена в листинге 9.5.

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace pr125_1 < // Класс со свойствами: class MyClass < // Закрытое поле-массив: private int[] nums; // Текстовое свойство без set-аксессора: public string content < // Метод вызывается при считывании значения свойства: get < // Если ссыпка на массив пустая: if( nums == null ) return "<>"; // Формирование текстовой строки: string txt = " + nums[0]; for(int k = 1; k < nums.Length; k++) < txt += "," + nums[k]; > txt += ">"; // Значение свойства: return txt; > > // Целочисленное свойство без get-аксессора: public int element < // Метод вызывается при присваивании // значения свойству: set < // Если ссылка на массив пустая: if( nums == null ) < // Создание массива из одного элемента: nums = new int[1]; // Значение единственного элемента массива: nums[0] = value; > else < // Если ссылка не пустая // Создание массива: int[] n = new int[nums.Length + 1]; // Заполнение массива: for(int k = 0; k < nums.Length; k++)< n[k] = nums[k]; >// Значение последнего элемента в массиве: n[nums.Length] = value; // Ссылка на созданный массив записывается в // поле объекта: nums = n; > > > // Свойство является ссылкой на массив: public int[] data < // Метод вызывается при считывании значения свойства: get < // Создание массива: int[] res = new int[nums.Length]; // Заполнение массива: for(int k = 0; k < nums.Length; k++) < res[k] = nums[k]; >// Значение свойства: return res; > // Метод вызывается при присваивании // значения свойству: set < // Создание массива: nums = new int[value.Length]; // Заполнение массива: for (int k = 0; k < value.Length; k++)< nums[k] = value[k]; > > > > // Класс с главным методом: class Program < // Главный метод: static void Main() < // Создание объекта: MyClass obj = new MyClass(); // Проверка содержимого массива из объекта: Console.WriteLine(obj.content); // Присваивание значения свойству element: obj.element = 10; // Проверка содержимого массива из объекта: Console.WriteLine(obj.content); // Присваивание значения свойству element: obj.element = 5; obj.element = 7; // Проверка содержимого массива из объекта: Console.WriteLine(obj.content); // Считывание значения свойства data: int[] A = obj.data; // Присваивание значения свойству element: obj.element = 12; // Отображение содержимого массива А: for(int k = 0; k < A.Length; k++) < Console.Write(A[k] + " "); > Console.WriteLine(); // Проверка содержимого массива из объекта: Console.WriteLine(obj.content); // Создание массива: int[] B = ; // Присваивание значения свойству data: obj.data = B; // Изменение значения элемента массива В: B[0] = 0; // Отображение содержимого массива В: for(int k = 0; k < B.Length; k++)< Console.Write(B[k] + " "); > Console.WriteLine(); // Проверка содержимого массива из объекта: Console.WriteLine(obj.content); // Задержка: Console.ReadLine(); > > >

Архив проекта можно взять здесь.

В результате выполнения программы получаем следующее.

Рис.1. Результат выполнения программы

Класс MyClass имеет закрытое поле nums , представляющее собой ссылку на целочисленный массив. Этот массив используется при описании свойств content , element и data . Свойство content текстовое, и у этого свойства есть только get -аксессор (свойство можно прочитать, но нельзя присвоить). Свойство возвращает текстовую строку со значениями элементов массива. При вызове get -аксессора для этого свойства в условной конструкции проверяется условие nums==null , истинное, если поле nums не ссылается на массив. Если так, то значением свойства возвращается строка «<>» .

Ключевое слово null означает пустую ссылку. Если переменной ссылочного типа (переменной массива или объектной переменной) не присвоено значение, то значение такой переменной — пустая ссылка (то есть равно null ).

Если же поле nums ссылается на массив, то формируется текстовая прока, содержащая значения элементов массива, и эта строка возвращается как значение свойства content .

Целочисленное свойство element не имеет get -аксессора, поэтому свойству можно присвоить значение, но нельзя узнать значение свойства. При присваивании значения свойству в массив nums добавляется новый элемент с присваиваемым значением. Для этого в теле set -аксессора в условной конструкции проверяется условие nums==null . Истинность условия означает, что поле nums на массив не ссылается. В таком случае командой

nums = new int[1];

создается массив из одного элемента, и значение этого элемента есть присваиваемое свойству значение:

nums[0] = value; .

Если условие nums==null в условной конструкции ложно, то командой

int[] n = new int[nums.Length + 1];

создается новый массив, размер которого на единицу больше размера массива, на который ссылается поле nums . Сначала выполняется поэлементное копирование значений из массива nums во вновь созданный массив. Остается незаполненным один последний элемент. Командой

n[nums.Length] = value;

этому элементу присваивается значение, которое по факту присваивается свойству element . Наконец, командой

nums = n;

в поле nums записывается ссылка на новый массив. Общий эффект получается такой, что в массиве, на который ссылается поле nums , появился дополнительный последний элемент.

Свойство data является ссылкой на целочисленный массив. Для свойства описаны два аксессора. Это означает, что свойству значением можно присвоить ссылку на массив и результатом свойства является также ссылка на массив.

В get -аксессоре для этого свойства командой

int[] res = new int[nums.Length];

создается массив такого же размера, что и массив, на который ссылается поле nums . Затем выполняется копирование массивов. Значением свойства является ссылка на новый созданный массив, являющийся копией массива, на который ссылается поле nums .

Свойство data значением возвращает ссылку на массив, который является копией массива, на который ссылается поле nums объекта.

В set -аксессоре для свойства data командой

nums = new int[value.Length];

создается новый массив, и ссылка на него записывается в поле nums . Здесь следует учесть, что ключевое слово value , обозначающее присваиваемое свойству значение, относится к типу int[] (тип свойства data ) — то есть является ссылкой на целочисленный массив и обрабатывается как массив. Размер такого массива вычисляется выражением value.Length . С помощью циклической конструкции выполняется копирование значений элементов из присваиваемого массива value в созданный массив nums.

В главном методе программы командой

MyClass obj = new MyClass();

создается объект obj класса MyClass . Его поле nums на массив не ссылается, в чем легко убедиться с помощью команды

Console.WriteLine(obj.content);

Присваивание значения свойству element командой

obj.element = 10;

приводит к тому, что в массиве nums появляется один элемент. После выполнения команд

obj.element = 5;
obj.element = 7;

там появляется еще два элемента.

На следующем этапе командой

int[] A = obj.data;

объявляется переменная массива А и в нее записывается ссылка на копию массива, на который ссылается поле nums объекта obj . Чтобы проверить, что это именно копия, а не сам массив nums , командой

obj.element = 12;

в массив nums объекта obj добавляется еще один элемент. При этом массив А остается неизменным, в чем легко убедиться, сравнив результат отображения содержимого массива А и массива nums из объекта obj .

int[] B = ;

создается целочисленный массив В , и командой

obj.data = B;

ссылка на массив присваивается значением свойству data объекта obj . В результате поле nums объекта получает значением ссылку на копию массива B . Действительно, проверка показывает, что после выполнения команды

B[0] = 0;

массив B меняется, а массив, на который ссылается поле nums объекта obj , остается таким, как до выполнения команды

B[0] = 0; .

На следующем шаге мы рассмотрим закончим изучение этого вопроса .

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *