Разработка приложений на языке C#. Полезные настройки. Особые спецификаторы формата, страница 16

Сформулируйте различия между методами GetUpperBound и GetLength.

Предположим, что мы захотели узнать размер памяти, занимаемой нашим массивом. Ответ на этот вопрос вы, конечно, знаете (6 * 4 = 24). Но мы хотим подтвердить эту оценку с помощью свойств или методов класса Array и типа System.UInt32. В программе на языке С++ для этой цели мы применили бы операцию sizeof. В рамках языка С# все массивы—это ссылки на память в области heap и операция sizeof работает только в блоке unsafe. Вне этого блока ответ можно получить с помощью класса Buffer, который позволяет легко манипулировать массивами примитивных типов (primitive types). Добавьте в метод TestArray фрагмент, который иллюстрирует некоторые возможности класса Buffer.

int[] a = { 1, 2, 3, 4, 5};  // Два массива

int[] b = { 0, 0, 0, 0, 0, 6, 7, 8, 9, 10};

int lenA = Buffer.ByteLength (a),  lenB = Buffer.ByteLength (b); // Размеры массивов в байтах

Console.WriteLine ("\n\nThe length of Array a: {0} bytes", lenA);

foreach (int i in a)  // Все элементы массива

  Console.Write("{0},  ",i);

Console.WriteLine("\n\nThe length of Array b: {0} bytes", lenB);

foreach (int i in b)

  Console.Write("{0},  ",i);

Buffer.BlockCopy (a, 0, b, 0, lenA);  // Интересная операция

Console.WriteLine("\n\nAfter Block copy operation array a :");

foreach (int i in a)

  Console.Write("{0},  ",i);

Console.WriteLine("\n\nArray b: ");

foreach (int i in b)

  Console.Write("{0},  ",i);

Console.WriteLine("\n\n");

Задание

·  Объявите трехмерный массив строк (без начальной инициализации). Сколько байт памяти он занимает? Вычислите в уме, класс Buffer не поможет, так как string не является primitive type.

·  Объявите трехмерный массив типа double без начальной инициализации. В другой строке кода инициализируйте его и присвойте какие-то значения.

·  Переопределите массив, объявленный в предыдущем задании так, чтобы изменились размерности по всем трем измерениям. При этом для массива будет выделена новая память (кто займется старой?).

Массивы массивов

Рассмотрим альтернативный способ объявления массивов, который в документации снабжен эпитетом jagged (рваный, неровный, см. Help→Reference). Такие массивы следует представлять как массивы массивов. Принципиальным отличием их от массивов предыдущего типа является то, что размерности подчиненных массивов могут быть разными. Технология использования таких массивов демонстрируются в следующем примере TestJagged. Добавьте вызов этого метода в ту же ветвь.

int[][] a =      // Объявляем массив массивов целых

{

  new int[]{1},

  new int[]{2,3,4},

  new int[]{5,6,7,8,9}

};

Console.WriteLine ("Jagged array:\n");

for (int i=0; i < a.GetLength(0); i++)  // 0-е измерение работает как и ранее

{

  Console.WriteLine();

      for (int j=0; j < a[i].GetLength(0); j++) // Число столбцов переменно, поэтому измерение 1 не работает

    Console.Write ("a[{0}][{1}] = {2},  ", i, j, a[i][j]);

}

Console.WriteLine("\n\nRank = " + a.Rank);

Console.WriteLine("Length = " + a.Length + '\n');

for (int i=0; i < a.GetLength(0); i++)

{

  foreach (int j in a[i])    // foreach выглядит по-другому

    Console.Write (j+", ");

}

Необычные массивы

Приходилось ли вам встречать математические алгоритмы, использующие отрицательные индексы в последовательностях? В теории управления, а, следовательно, и в теории дифференциальных уравнений такие алгоритмы существуют. Класс Array позволяет работать с массивами, границы которых произвольны. Следующий пример иллюстрирует это.

Array a = Array.CreateInstance(typeof(int), new int[] { 2, 3, 4 }, new int[] { -2, 0, 2 });

for (int i = a.GetLowerBound(0); i <= a.GetUpperBound(0); i++)

  for (int j = a.GetLowerBound(1); j <= a.GetUpperBound(1); j++)

    for (int k = a.GetLowerBound(2); k <= a.GetUpperBound(2); k++)

      a.SetValue(i + j + k, new int[] { i, j, k });