Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Podbelsky_V_V_C_Bazovy_kurs.pdf
Скачиваний:
69
Добавлен:
02.06.2015
Размер:
1.73 Mб
Скачать

114

Г л а в а 7

 

 

static void Main()

{

double[,] ar = {

{10, -7, 0, 7},

{-3, 2.099, 6, 3.901},

{5, -1, 5, 6},

};

Console.WriteLine("ar.Rank = " + ar.Rank); Console.WriteLine("ar. = " + ar.GetUpperBound(1); Console.WriteLine("ar.GetLength(1) = " +

ar.GetLength(1));

for (int i = 0; i < ar.GetLength(0); i++, Console. WriteLine())

for (int j = 0; j <= ar.GetUpperBound(1); j++) Console.Write("\t"+ ar[i, j]);

}

}

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

ar.Rank = 2

 

 

ar.GetUpperBound(1) = 3

 

 

ar.GetLength(1) = 4

 

 

10 -7

0

7

 

3

2,099

6

3,901

5

-1

5

6

В программе определён и инициализирован двумерный массив с элементами типа double. Результаты выполнения программы поясняют особенности свойств и методов типа массивов, производного от класса Array. Обратите внимание, что GetUpperBound(1) – верхняя граница второго индекса, а не количество значений этого индекса.

7.5. Массивы массивов и поверхностное копирование

Итак, массив массивов представляет собой одномерный массив, элементами которого являются ссылки на массивы следующего (подчиненного) уровня. Этот факт требует особого внимания, так как затрагивает фундаментальные вопросы ко-

Массивы

115

 

 

пирования ссылок и тех объектов, которые ими адресуются. Независимо от того, какого вида массив мы рассматриваем,

присваивание ссылке на массив значения другой ссылки на уже существующий массив (на объект с типом массива) приводит к появлению двух ссылок на один массив. Это мы уже иллюстрировали и разобрали.

Метод Clone() позволяет создать новый экземпляр массива. В программе 07_04.cs показано, что, изменяя один из одномерных массивов-копий, мы не изменяем второй. Следующая программа иллюстрирует применение копирования к многомерному массиву:

// 07_08.cs двумерный массив полное клонирование using System;

class Program

{

static void Main()

{

int size;

do Console.Write("size = ");

while (!int.TryParse(Console.ReadLine(), out size)||size<1);

int[,] one = new int[size, size]; Console.WriteLine("Массив one:");

for (int i = 0; i < size; i++, Console.WriteLine()) for (int j = 0; j < size; j++)

{

if (i == j) one[i, j] = 1; Console.Write(one[i, j] + "\t");

}

Console.WriteLine("one.Length = " + one.Length); int[,] two = (int[,])one.Clone(); // клонирование two[0, 0] = -size;

Console.WriteLine("Массив two:");

for (int i = 0; i < size; i++, Console.WriteLine()) for (int j = 0; j < size; j++)

Console.Write(two[i, j] + "\t"); Console.WriteLine("Массив one:");

for (int i = 0; i < size; i++, Console.WriteLine()) for (int j = 0; j < size; j++)

Console.Write(one[i, j] + "\t");

} }

116 Г л а в а 7

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

size = 4<ENTER>

 

Массив one:

 

1

0

0

0

0

1

0

0

0

0

1

0

0

0

0

1

one.Length = 16

 

Массив two:

 

-4

0

0

0

0

1

0

0

0

0

1

0

0

0

0

1

Массив one:

 

1

0

0

0

0

1

0

0

0

0

1

0

0

0

0

1

В программе определена ссылка two типа int[,], и ей присвоен результат копирования массива, связанного со ссылкой one, имеющей тот же тип int[,]. Выведена единичная матрица, адресованная ссылкой one, затем изменен обычным присваиванием один элемент массива–копии:

two[0,0]=-size;

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

Программы 07_04.cs и 07_08.cs работают с массивами, у которых по одному спецификатору размерности. В первом случае массив одномерный, во второй программе клонируется двумерный массив. Применяя метод Clone() к массиву массивов, мы сталкиваемся с очень важной особенностью. Строго говоря, действия метода остаются прежними – он создает массив-ко- пию и присваивает его элементам значения элементов масси- ва-оригинала. Однако в этом случае копирования тех подчинённых массивов, на которые "смотрят" ссылки-элементы мас- сива-оригинала, не происходит. Выполняется так называемое поверхностное или поразрядное копирование. Иначе и быть не должно – "не знает" метод Clone(), что код, который является

Массивы

117

 

 

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

Таким образом, копируя с помощью метода Clone() массив массивов, мы получаем два экземпляра массива верхнего уровня, элементы которых адресуют одни и те же участки памяти, выделенные для подчиненных массивов объекта-оригинала.

В качестве иллюстрации указанной ситуации приведем следующую программу, построенную на основе 07_06.cs:

/ 07_09.cs непрямоугольный массив клонирование

поверхностное! using System; class Program

{

static void Main()

{

int size;

do Console.Write("size = ");

while (!int.TryParse(Console.ReadLine(), out size)||size<1);

int[][] tre = new int[size][]; for (int j = 0; j < size; j++)

{

tre[j] = new int[j + 1]; tre[j][j] = j + 1;

}

Console.WriteLine("Массив tre:");

for (int i = 0; i < tre.Length; i++, Console.WriteLine()) for (int j = 0; j < tre[i].Length; j++)

Console.Write(tre[i][j] + "\t"); Console.WriteLine("tre.Length = " + tre.Length); int[][] two = (int[][])tre.Clone();

two[0][0] = - size; Console.WriteLine("Массив two:");

for (int i = 0; i < two.Length; i++, Console.WriteLine()) for (int j = 0; j < two[i].Length; j++)

Console.Write(two[i][j] + "\t"); Console.WriteLine("Массив tre:");

for (int i = 0; i < tre.Length; i++, Console.WriteLine()) for (int j = 0; j < tre[i].Length; j++)

Console.Write(tre[i][j] + "\t");

} }

118

Г л а в а 7

 

 

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

size = 4<ENTER>

Массив tre:

1

02

0

0

3

 

0

0

0

4

tre.Length = 4

Массив two: -4

02

0

0

3

 

0

0

0

4

Массив tre:

 

-4

 

 

 

02

0 0 3

0 0 0 4

В программе определена ссылка two типа int[][], и ей присвоен результат копирования (клонирования) "треугольного" массива, адресованного ссылкой tre, имеющей тип int[][]. С помощью оператора

two[0][0] = - size;

изменен один целочисленный элемент «нижнего уровня» массива массивов. После присваивания изменилось значение, соответствующее выражению tre[0][0].

Контрольные вопросы

1.Являются ли типы массивов типами значений?

2.Какое значение имеет индексирующее выражение при обращении к первому элементу одномерного массива?

3.Какой тип может иметь индексирующее выражение?

4.Где размещается (в стеке или в управляемой куче) ссылка на массив?

5.При выполнении какой операции создается объект класса массивов?

6.Что такое класс массивов?

Массивы

119

 

 

7.Какие значения принимают элементы массива при отсутствии в его определении инициализатора?

8.Какова структура инициализатора массива?

9.Чем определяется количество инициализирующих выражений в инициализаторе массива?

10.Объясните назначение всех элементов цикла foreach.

11.Каково назначение и возможности переменной цикла foreach.

12.Можно ли изменить размер массива-объекта после его создания?

13.Можно ли определить размер массива-объекта в процессе выполнения программы?

14.Назовите свойства массивов, унаследованные ими от класса Array.

15.Приведите примеры нестатических методов одномерных массивов.

16.Приведите примеры статических методов одномерных массивов.

17.В чём различия методов Copy() и Clone()?

18.Что такое размерность массива?

19.Что такое спецификатор размерности массива?

20.Допустимо ли динамическое определение размеров многомерных массивов?

21.Чему равно свойство Length для многомерного массива?

22.С помощью каких средств можно получить размер многомерного массива по нужному измерению?

23.Сколько спецификаторов размерности в объявлении типа четырёхмерного массива?

24.Перечислите синтаксические отличия массива массивов от двумерного массива.

25.Сколько операций new в определении объекта трехмерного массива?

26.Чему равно свойство Rank массива массивов?

27.В каком случае при клонировании массива проявляется эффект поверхностного копирования?

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]