Понятие массивов C Sharp
Массив - это набор элементов данных, для доступа к которым применяется числовой индекс. Выражаясь более конкретно, массив представляет собой набор расположенных рядом элементов данных одного и того же типа (массив элементов int, массив элементов string). Объявлять, заполнять и получать доступ к массиву в языке C Sharp довольно просто. В целях иллюстрации создам новый проект консольного приложения.
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Баловство с массивами");
SimpleArrays();
Console.ReadLine();
}
static void SimpleArrays()
{
Console.WriteLine("Создание простых массивов");
// Создать массив int, содержащий 3 элемента с индексами 0,1,2.
int[] myInts = new int[3];
// Создать массив string, содержащий 100 элементов с индексами 0-99.
string[] myString = new string[100];
Console.WriteLine();
}
}
Внимательно взгляните на комментарии в коде. При объявлении массива C Sharp с использованием подобного синтаксиса число, указанное в объявлении, обозначает общее количество элементов, а не верхнюю границу. Кроме того, нижняя граница в массиве всегда начинается с 0. Таким образом, в результате записи int[] myInts = new int[3] получается массив, который содержит три элементов, проиндексированные по позициям 0,1,2.
После определения переменной массива можно переходить к заполнению элементов от индекса к индексу, как показано ниже в модифицированном методе SimpleArrays():
statuc void SimpleArrays()
{
Console.WriteLine("Создание простых массивов");
// Создать и заполнить массив из трех целочисленных значений.
int[] myInts = new int[3];
myInts[0] = 100;
myInts[1] = 200;
myInts[2] = 300;
// Вывести все значения.
foreach(int i in myInts)
Console.WriteLine(i);
Console.ReadLine();
}
---Вывод в консоль ---
Баловство с массивами
Создание простых массивов
100
200
300
- На заметку! Имейте в виду, что если массив объявлен, но его элементы явно не заполнены по каждому индексу, то они получат стандартное значение для соответствующего типа данных(например, элементы массива bool будут установлены в значение false, а элементы массив int будут 0).
Синтаксис инициализации массивов C Sharp
В дополнение к заполнению массива элемент за элементом есть также возможность заполнять его с применением синтаксиса инициализации массива. Для этого понадобится указать значения всех элементов массива в фигурных скобках ({}). Такой синтаксис удобен при создании массива известного размера, когда нужно быстро задать его начальные значения, Например, вот как выглядит альтернативные версии объявления массива:
static void ArrayInitialization()
{
Console.WriteLine("Инициализация массива");
// Синтаксис инициализации массива с использованием ключевого слова new.
string[] stringArray = new string[]
{"один", "два", "три"};
Console.WriteLine("stringArray имеет {0} элементов", stringArray.Length);
// Синтаксис инициализации массива без использования ключевого слова new.
bool[] boolArray = {false.false,true};
Console.WriteLineP("boolArray имеет {0} элементов", boolArray.Length);
// Инициализация массива с применением ключевого слова new и указанием размера.
int[] intArray = new int[4] {20, 22, 23, 0};
Console.WriteLine("intArray имеет {0} элементов", intArray.Length);
Console.ReadLine();
}
---Вывод в консоль ---
Инициализация массива
stringArray имеет 3 элементов
boolArray имеет 3 элементов
intArray имеет 4 элементов
Обратите внимание, что в случае использования синтаксиса с фигурными скобками нет необходимости указывать размер массива(как видно на примере создания переменной stringArray), поскольку размер автоматически вычисляется на основа количества элементов внутри фигурных скобок. Кроме того, применять ключевое слово new не обязательно (как при создании массива boolArray).
В случае объявления int Array снова вспомните, что указанное числовое значение представляет количество элементов в массива, а не верхнюю границу. Если объявленный размер и количество инициализаторов не совпадают (инициализаторов слишком много или не хватает), тогда на этапе компиляции возникает ошибка. Пример представлен ниже:
// Несоответствие размера и количества элементов!
int[] intArray = new int[2] {20, 22, 23, 0};
Неявно типизированные локальные массивы
Ключевое слово var позволяет определять переменную, тип которой выводится компилятором. Аналогичным образом ключевое слово var можно использовать для определения неявно типизированных локальных массивов. Такой подход позволяет выделять память под новую переменную массива, не указывая тип элементов внутри массива (обратите внимание, что применение этого подхода предусматривает обязательное использование ключевого слова new):
static void Main(string[] args)
{
Console.WriteLine("Неявная инициализация массива");
// Переменная а на самом деле имеет тип int[].
var a = new[] {1, 10, 100, 1000};
Console.WriteLine("a есть a: {0}", a.ToString());
// Переменная b на самом деле имеет тип double[].
var b = new[] {1, 1.5, 2, 2.5};
Console.WriteLine("b есть b: {0}",b.ToString());
//Переменная c на самом деле имеет тип string[].
var c = new[] {"hello", "null", "world"};
Console.WriteLine("c есть с: {0}",c.ToString());
Console.ReadLine();
}
---Вывод в консоль ---
Неявная инициализация массива
a есть a: System.Int32[]
b есть b: System.Double[]
c есть с: System.String[]
Разумеется, как и при создании массива с применением явного синтаксиса C Sharp, элементы в списке инициализации массива должны принадлежать одному и тому же типу (например, должны быть все int, все string). В отличие от возможных ожиданий, неявно типизированный локальный массив не получает по умолчанию тип System.Object, так что следующий код приведет к ошибке на этапе компиляции:
// Ошибка! Смешанные типы!
var d = new[] {1, "one", 2, "two", false};
Определение массива объектов
В большинстве случаев массив определяется путем указания явного типа элементов, которые могут в нем содержаться. Хотя это выглядит довольно прямолинейным, существует одна важная особенность. Изначальным базовым классом для каждого типа (включая фундаментальные типы данных) в системе типов .NET является System.Object. С учётом такого факта, если определить массив типа данных System.Object, то его элементы могут представлять все что угодно. Взгляните на следующий код:
static void ArrayOfObjects()
{
Console.WriteLine("Массив объектов");
// Массив объектов может содержать все что угодно.
object[] myObjects = new object[4];
myObjects[0] = 10;
myObjects[1] = false;
myObjects[2] = new DateTime(1969, 3, 24);
myObjects[3] = "Вселенная";
foreach (object obj in myObjects)
{
// Вывести тип и значение каждого элемента в массиве.
Console.WriteLine("Type: {0}, Value: {1}", obj.GetType(), obj);
}
Console.ReadLine();
}
---Вывод в консоль ---
Массив объектов
Type: System.Int32, Value: 10
Type: System.Boolean, Value: False
Type: System.DateTime, Value: 24.03.1969 0:00:00
Type: System.String, Value: Вселенная
Здесь во время прохода по содержимому массива myObjects для каждого элемента выводится лежащий в основе тип, получаемый с помощью метода GetType() класса System.Object, и его значение. Не вдаваясь пока в детали метода System.Object. GetType(), просто отмечу, что он может использоваться для получения полностью заданного имени элемента
Работа с многомерными массивами
В дополнение к одномерным массивам, которые вы видели до сих пор, язык C Sharp также поддерживает два вида многомерных массивов. Первый вид называется прямоугольным массивом, который имеет несколько измерений, содержащиеся в нем строки обладают одной и той же длиной. Прямоугольный многомерный массив объявляется и заполняется следующим образом:
static void Main (string[] args)
{
Console.WriteLine("Прямоугольный многомерный массив");
// Инициализация прямоугольного многомерного массива
int [,] myMatrix;
myMatrix = new int[3,4];
// Заполнить массив (3*4).
for (int i = 0; i < 3; i++)
for(int j = 0; j < 4; j++)
myMatrix[i,j] = i*j;
// Вывести содержимое массива (3*4).
for (int i = 0; i < 3; i++)
{
for(int j = 0; j < 4; j++)
Console.Write(myMatrix[i,j] + "\t");
Console.WriteLine();
}
Console.ReadLine();
}
---Вывод в консоль ---
Прямоугольный многомерный массив
0 0 0 0
0 1 2 3
0 2 4 6
Второй вид многомерных массивов носит название зубчатого (или ступенчатого) массива. Такой массив содержит какое-то число внутренних массивов, каждый из которых может иметь отличающийся верхний предел. Вот пример:
static void Main (string[] args)
{
Console.WriteLine("Зубчатый многомерный массив");
// Инициализация зубчатого многомерного массива(т.е массив массивов)
//Здесь мы имеем массив из 5 разных массивов.
int [][] myJagArray = new int[5][];
//Создать зубчатый массив.
for (int i = 0; i < myJagArray.Length; i++)
myJagArray[i] = new int[i+7];
// Вывести все строки (помните, что каждый элемент имеет стандартное значение 0).
for (int i = 0; i < 5; i++)
{
for(int j = 0; j < myJagArray[i].Length; j++)
Console.Write(myJagArray[i][j] + " ");
Console.WriteLine();
}
Console.ReadLine();
}
---Вывод в консоль ---
Зубчатый многомерный массив
0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
Использование массивов в качестве аргументов и возвращаемых значений
После создания массив можно передавать как аргумент или получать его в виде возвращаемого значения. Например, приведенный ниже метод PrintArray() принимает входной массив значений int и выводит все его элементы на консоль, а метод GetStringArray() заполняет массив значений string и возвращает его вызывающему коду:
static void Main (string[] args)
{
Console.WriteLine("Массивы как параметры и возвращаемые значения");
// Передать массив в качестве параметра.
int[] ages = {20, 22, 23, 0};
PrintArray(ages);
//Получить массив как возвращаемое значение.
string[] strs = GetStringArray();
foreach(string s in strs)
Console.WriteLine(s);
Console.ReadLine();
}
static void PrintArray(int[] myInts)
{
for(int i = 0; i < myInts.Length; i++)
Console.WriteLine("Элемента {0} это {1}", i, myInts[i]);
}
static string[] GetStringArray()
{
string[] theStrings = {"Hello", "from", "GetStringArray"};
return theStrings;
}
---Вывод в консоль ---
Массивы как параметры и возвращаемые значения
Элемента 0 это 20
Элемента 1 это 22
Элемента 2 это 23
Элемента 3 это 0
Hello
from
GetStringArray
К настоящему моменту вы должны освоить процесс определения, заполнения и исследования содержимого переменной типа массива C Sharp. Для полноты картины давайте проанализируем роль класса System.Array
Базовый класс System.Array
Каждый создаваемый массив получает значительную часть своей функциональности от класса System.Array. Общие члены этого класса позволяют работать с массивом, применяя согласованную объектную модель. В таблице ниже приведено краткое описание наиболее интересных членов класса Systeam.Array(полное описание всех его членов можно найти в документации .NET Framework 4.7 SDK ).
Давайте посмотрим на некоторые из членов в действии. Показанный далее вспомогательный метод использует статические методы Reverse() и Clear() для вывода на консоль информации о массиве строковых типов:
static void Main(string[] args)
{
Console.WriteLine("Работа с System.Array");
// Инициализировать элементы при запуске.
string[] gothicBands = {"Tones on Tail", "Bauhaus", "Sisters of Mercy"};
// Вывести имена в порядке их объявления.
Console.WriteLine("Вот этот массив:");
for (int i = 0; i < gothicBands.Length; i++)
{
//Вывести имя.
Console.Write(gothicBands[i] + ", ");
}
Console.WriteLine('\n');
// Обратить порядок следования элементов...
Array.Reverse(gothicBands);
Console.WriteLine("Перевернутый массив");
// ... и вывести их.
for(int i = 0; i < gothicBands.Length; i++)
{
//Вывести имя.
Console.Write(gothicBands[i] + ", ");
}
Console.WriteLine('\n');
// Удалить все элементы кроме первого.
Console.WriteLine("Убрали все, кроме одного...");
Array.Clear(gothicBands,1,2);
for(int i = 0; i < gothicBands.Length;i++)
{
//Вывести имя.
Console.Write(gothicBands[i]+ ", ");
}
Console.WriteLine();
Console.ReadLine();
}
---Вывод в консоль ---
Работа с System.Array
Вот этот массив:
Tones on Tail, Bauhaus, Sisters of Mercy,
Перевернутый массив
Sisters of Mercy, Bauhaus, Tones on Tail,
Убрали все, кроме одного...
Sisters of Mercy, , ,
Обратите внимание, что многие члены класса System.Array определены как статические и потому вызываются на уровне класса(примерами могут служить методы Array.Sort() и Array.Reverse()). Методам подобного рода передается массив, подлежащий обработке. Другие члены System.Array(такие как свойство Length) действуют на уровне объекта, поэтому могут вызываться прямо на типе массива.
Методы и модификаторы параметров
Для начала мы займемся исследованием деталей определения методов. Подобно методу Main() ваши специальные методы могут принимать или не принимать параметры и возвращать или не возвращать значения вызывающему коду. В последующих нескольких статьях вы увидите, что методы могут быть реализованы внутри области видимости классов или структур (и заодно прототипироваться внутри интерфейсных типов), а также декорированы разнообразными ключевыми словами(например, static, virtual, public,new) с целью уточнения их поведения. До настоящего момента каждый их рассматриваемых методов следовал такому базовому формату:
class Program
{
//static возвращаемыйТип ИмяМетода(список параметров)
{
/*Реализация*/
}
static int Add(int x, int y)
{
return x+y;
}
}
Возвращаемые значения и члены, сжатые до выражений
Вы уже знаете о простых методах, возвращающих значения, вроде метода Add(). В версии C Sharp 6 появились члены, сжатые до выражений, которые сокращают синтаксис написания однострочных методов. Например, метод Add() можно переписать следующим образом:
static int Add(int x, int y) => x+y;
Обычно такой прием называют "синтаксическим сахаром", имея в виду, что генерируемый код IL не изменяется по сравнению с первоначальной версией метода. Это просто другой способ написания метода. Одни находят его более легким для восприятия, другие - нет, так что выбор стиля зависит от ваших персональных предпочтений (или предпочтений команды).
Данный синтаксис также применим к свойствам, предназначенным только для чтения
В версии C Sharp 7 возможность сжатия до выражений была расширена с целью охвата однострочных конструкторов, финализаторов, а также средств доступа get и set для свойств и индексаторов. Вы будете встречать смесь использования членов, сжатых до выражений, и традиционного подхода.
- На заметку! Не пугайтесь операции =>. Это лямбда-операция, которая будет рассмотрена позже в статьях. Пока просто считайте их сокращением при написании однострочных операторов.
Модификаторы параметров для методов
Стандартный способ передачи параметра в функцию - по значению. Попросту говоря, если вы не помечаете аргумент каким-то модификатором параметра, тогда в функцию передается копия данных, Как будет объяснятся в следующих статьях, то, что в точности копируется, будет зависеть от того, относится параметр к типу значения или к ссылочному типу.
Хотя определение метода в C Sharp выглядит достаточно понятно, с помощью модификаторов, описанных ниже в таблице, можно управлять способом передачи аргументов интересующему методу.
Проиллюстрированные модификаторы будут объяснятся в следующих статьях и их использование и частично затронем их роль. Продолжение в следующих статьях.
Отбрасывание
Отбрасывание касается временных, фиктивных переменных, которые намеренно не используется. Значения им не присваивались, и возможно для них даже не выделялась память. Отбрасывание способно обеспечить выигрыш в производительности, но самое меньшее оно может улучшить читабельность кода. Отбрасывание может применяться с параметрами out, кортежками, сопоставлением с образцом и даже автономными переменными.
Вероятно, вас интересует, для чего может понадобиться присваивание значения отбрасываемой переменной. Как будет показано в следующих статьях, это становится удобным при асинхронном программировании.
Конец
Спасибо, если вы прочитали эту статью. Надеюсь вы что-то новое узнали для себя, и конечно же поняли. Подпишитесь, поставьте лайк, напишите комментарий, поддержите меня. Хотелось бы увидеть как улучшать статьи и чего не хватает. Буду анализировать и улучшать контент. Еще раз спасибо, до свидания! :)