//Создаем ломаный массив
for (int i=0; i<myJagArray.Length; i++)
{
myJagArray[i] = new int[i+7];
}
//Выводим каждую строку массива. По умолчанию все элементы=0
for (int i=0; i<5; i++)
{
Console.Write("Длина {0}-й строки равна {1}:\t",i,myJagArray[i].Length);
for (int j=0; j<myJagArray[i].Length; j++)
{
Console.Write(myJagArray[i][j]+" ");
}
Console.WriteLine(); }
Рис. 16. Вывод размера строки и элементов ломаного массива
Базовым для всех массивов в С# является класс System.Array. Из-за этого происходят все различия между массивами в С++ и С#.
Некоторые из методов этого класса приведены в табл. 6.
Таблица 6
Член класса |
Назначение |
BinarySearch() |
Этот статический метод можно использовать только тогда, когда массив реализует интерфейс IComparer. Если интерфейс реализован, то этот метод позволяет найти элемент массива |
Clear() |
Этот статический метод позволяет очистить указанный диапазон элементов (числовые элементы приобретут 0, объекты – NULL) |
CopyTo() |
Копирует элементы из исходного массива в массив назначения |
GetEnumerator() |
Возвращает интерфейс IEnumerator для указанного массива |
GetLength() Length |
Метод определяет число элементов в указанном измерении массива. Свойство Length (только для чтения) дает количество элементов массива |
GetLowerBound() |
Определяет нижнюю границу измерения массива |
GetUpperBound() |
Определяет верхнюю границу измерения массива |
GetValue() SetValue() |
Возвращает или устанавливает значение указанного индекса для массива. Перегружены для нормальной работы с одномерными и многомерными массивами |
Reverse() |
Расставляет элементы одномерного массива в обратном порядке |
Sort() |
Сортируется одномерный массив встроенных типов данных. Если элементы массива поддерживают интерфейс ICompare, то метод может сортировать массив из пользовательских типов |
Пример использования членов System.Array:
string [] myName = new string[5]
{
"Ваня",
"Света",
"Петя",
"Людмила",
"Денис"
};
Console.WriteLine("Имена в массиве");
for (int i=0; i<myName.Length; i++)
Console.Write(myName[i]+"\t");
Console.WriteLine();
//Выводим имена в обратном порядке
Array.Reverse(myName);
Console.WriteLine("\nИмена в обратном порядке");
for (int i=0; i<myName.Length; i++)
Console.Write(myName[i]+"\t");
Console.WriteLine();
//Очищаем все имена, кроме последнего
Console.WriteLine("\nОчистили имена, кроме последнего");
Array.Clear(myName,1,4);
for (int i=0; i<myName.Length; i++)
Console.Write(myName[i]+"\t");
Console.WriteLine();
Рис. 17. Демонстрация работы методов Array
В C# функции существуют только как методы некоторого класса, они не существуют вне класса.
Синтаксис объявления метода позволяет однозначно определить, чем является метод - процедурой или функцией.
Функция отличается от процедуры двумя особенностями:
- всегда вычисляет некоторое значение, возвращаемое в качестве результата функции;
- вызывается в выражениях.
Процедура C# имеет свои особенности:
- возвращает формальный результат void, указывающий на отсутствие результата;
- вызов процедуры является оператором языка;
- имеет входные и выходные аргументы, причем выходных аргументов - ее результатов - может быть достаточно много.
Синтаксически в определении метода различают две части - заголовок и тело метода:
<заголовок_метода> {<тело_метода>}
Например:
void A() {...};
int B(){...);
public void C(){...};
Синтаксис заголовка метода:
[<атрибуты>][<модификаторы>] <типРезультатаФункции> <имя_метода> ([<списокФормАрг>])
Квадратные скобки показывают, что атрибуты и модификаторы могут быть опущены при описании метода.
Обязательным при описании заголовка является указание типа результата, имени метода и круглых скобок, даже если сам список формальных аргументов отсутствует.
Для различения методов очень часто используют такой термин как сигнатура метода. Всегда следует относиться внимательно к этому словосочетанию и рассматривать его в контексте. Сам термин «сигнатура» необходим для перегрузки (overload) и переопределения (override) методов.
В литературе есть различные трактовки сигнатуры. Например, сигнатура задает: возвращаемое значение метода и список формальных аргументов [5]; имя метода и список формальных аргументов [4]; параметры и возвращаемое значение функции [2].
В сигнатуру не входят имена формальных аргументов т.к. важны лишь их типы.
Синтаксис объявления формального аргумента таков:
[ref | out | params] <типАргумента> <имяАргумента>
Обязательным является указание типа и имени аргумента.
Тип аргумента быть любым скалярным типом, массивом, классом, структурой, интерфейсом, перечислением, функциональным типом.
Можно при вызове метода передавать ему произвольное число фактических аргументов. Для этого в списке формальных аргументов необходимо задать ключевое слово params.
Оно задается 1 раз и указывается только для последнего аргумента списка, объявляемого как массив произвольного типа.
При вызове метода этому формальному аргументу соответствует произвольное число фактических аргументов.
Все аргументы метода разделяются на три группы:
- входные,
- выходные (out),
- обновляемые (ref).
Аргументы первой группы передают информацию методу, их значения в теле метода только читаются.
Аргументы второй группы представляют собой результаты метода, они получают значения в ходе работы метода. Выходные аргументы всегда объявляться с ключевым словом out.
Если аргумент объявлен с ключевым словом out, то в теле метода обязательно должен присутствовать оператор присваивания, задающий значение этому аргументу. В противном случае возникает ошибка компиляции. Более того, ошибка возникает, если со словом out объявлены по сути обновляемые параметры.
Аргументы ref более гибкие и объединяют оба действия. Обновляемые аргументы всегда должны сопровождаться ключевым словом ref.
Рассмотрим различные виды параметров на примере перегруженных методов. Перегруженные методы имеют одно и то же имя, но различаются списком параметров. Важно, что нельзя перегружать методы, различающиеся только возвращаемыми значениями. Методы имеют имя А() и рассчитывают сумму кубов произвольного числа аргументов.
static void A(out long p2, int p1)
{
p2 =(long) Math.Pow(p1,3);
Console.WriteLine("Метод A-1");
}
static void A(out long p2, params int[] p)
{
p2=0;
for(int i=0; i <p.Length; i++)
p2 += (long)Math.Pow(p[i],3);
Console.WriteLine("Метод A-2");
}
static void A(out double p2, double p1)
{
p2 = Math.Pow(p1,3);
Console.WriteLine("Метод A-3");
}
static void A(out double p2, params double[] p)
{
p2=0;
for(int i=0; i <p.Length; i++)
p2 += Math.Pow(p[i],3);
Console.WriteLine("Метод A-4");
}
В примере все методы - процедуры. Первый аргумент у всех четырех перегруженных методов – выходной (записывается со словом out), в теле метода ему присваивается вычисленное значение.
2 метода используют ключевое слово params для последнего аргумента. При вызове этих методов указанному аргументу будет соответствовать несколько фактических аргументов, число которых может быть произвольным. Заранее можно сказать, что массивы – аргументы метода не обязательно снабжать словом params.
Если мы работаем с функцией, то в теле функции должен быть хотя бы один оператор, возвращающий значение функции: return (<Выражение>).
Переменные, описанные в блоке, локализованы в нем: живут и видны только внутри него.
Если вызвать процедуру в выражении, то возникнет ошибка компиляции.
Вызов процедуры или функции имеет один и тот же синтаксис:
<имяМетода>([<списокФактическихАргументов>])
Формальный аргумент, задаваемый при объявлении метода - это всегда имя аргумента (идентификатор). Фактический аргумент - это выражение, значительно более сложная синтаксическая конструкция. Синтаксис фактического аргумента:
[ref | out] <выражение>