Architecture Net или что такое Microsoft.NET?




Класс System::Array (Система::МAССИВ)

В отличие от массивов в обычном C++, которые являются простым типом указателя, управляемые массивы являются полноценными управляемыми объектами, расположенными в динамически распределяемой области. System: : Array (Система::Массив) — абстрактный класс, являющийся базовым для всех управляемых массивов. Для определения неуправляемых массивов можно использовать синтаксис обычного C++; для определения же управляемых массивов следует использовать либо ключевое слово _дс (сборщик мусора), либо указывать, что элементы массива относятся к управляемому типу. Далее приведены примеры определения массивов. Ключевое слово _дс (сборщик мусора) и управляемые типы подробнее рассмотрены ниже. Обратите внимание на две закомментированные строки, в которых при определении массива задается его величина. Величину массива можно задавать при определении неуправляемого (располагаемого в стеке) массива, но не при определении управляемого массива (располагаемого в динамически распределяемой области). Причина в том, что, подобно всем остальным управляемым типам, управляемый массив располагается в динамически распределяемой области, а не в стеке.

//ArraySyntax.срр
fusing <mscorlib.dll>
using namespace System;
// использовать пространство имен Система;
ttpragma warning(disable : 4101)
// уничтожить предупреждение о переменной, на которую нет ссылки:
// предупреждение (отключить: 4101)
void main(void) {
// традиционный синтаксис неуправляемого массива
int *pintUnManagedArrayOnHeap = new int [5];
int intUnManagedArray[5]; // нет ошибки для неуправляемого
// массива
// синтаксис управляемого массива,
// используется ключевое слово _дс (сборщик мусора) int intManagedArrayOnHeap _дс[] = new int _дс[5]; //int intManagedArray _gc[5]; // ошибка для управляемого
// массива
// синтаксис управляемого массива, используется
// управляемый тип элемента
String *strManagedArrayOnHeap[] = new String* [5]; // Строка
//String *strManagedArray[5]; // ошибка для управляемого
// массива }

Управляемые массивы имеют некоторые дополнительные, по сравнению с неуправляемыми массивами, свойства и ограничения.

  • Управляемый массив можно определить только в управляемой динамически распределяемой области памяти. Его нельзя поместить вне кучи (т.е. он не может быть расположен в стеке).
  • Описание управляемого массива не должно содержать размер массива, так как это предполагало бы его размещение вне динамически распределяемой области памяти. Вместо этого размер массива указывается при использовании оператора new (создать), создающего объект-массив, содержащийся в управляемой динамически распределяемой области памяти.
  • Все управляемые массивы являются потомками класса System: :Array (Система::Массив), так что методы этого класса, как, например, Сору (Копировать), GetLength и GetType, также как и методы класса System: :Object (Система::Объект), наподобие ToString и Equals (Равняется), могут использоваться в любом управляемом массиве.
  • При попытке доступа к элементу управляемого массива производится проверка принадлежности к диапазону, т.е. контроль границ. Одна из самых распространенных ошибок — обращение к несуществующему объекту по адресу, указывающему за пределы массива. При попытке обратиться к элементу, номер которого не попадает в диапазон индексов элементов, возникает исключение IndexOutOfRangeException.

Следующий пример показывает, как можно использовать обработчик исключений при попытке доступа к несуществующему элементу управляемого массива. Обратите внимание, что массив содержит пять элементов, а в цикле производится попытка установить значение шестого. Программа в обычном C++ выполнила бы такое действие, изменив содержимое памяти за пределами массива. Никто не скажет точно, чем это могло бы закончиться. При проверке корректности адреса выполняются два действия: во-первых, предотвращается изменение содержимого памяти за пределами массива; во-вторых, программе сообщается, что возникла подобная ситуация, тем самым давая возможность исправить ошибку еще на стадии тестирования. В обычном C++ такая ошибка часто не проявляется до тех пор, пока программа, по непонятным причинам, не прекращает работу, обычно в месте кода, далеко отстоящем от самой ошибки. И, разумеется, согласно закону Мэрфи, эта ошибка обнаруживается только тогда, когда программа уже передана заказчику. //IndexOutOfRangeException.срр

#using <mscorlib.dll> using namespace System;
// использовать пространство имен Система/void main () {
int intArray _gc[]= new int _gc[5]; // сборщик мусора [5]
for (int i=0; i<6; i++) // больше чем есть!!!
{
try {
intArray[i] = i; }
catch (IndexOutOfRangeException *piore) {
// нужно сделать кое-что более полезное, // чтобы здесь восстановиться Console::WriteLine("Oooops!"); Console::WriteLine(piore->get_Message()); } } }

Программа напечатает:

Oooops!
Exception of type System.IndexOutOfRangeException was thrown.

Перевод такой [Добавлен редактором русского перевода. — Прим. ред.]:

Возникло исключение типа Система.IndexOutOfRangeException.

Как и для неуправляемых массивов, нумерация элементов в управляемых массивах начинается с нуля. Однако, значения элементов управляемых массивов, в отличие от элементов неуправляемых массивов, автоматически инициализируются значением, принятым по умолчанию для каждого типа элемента массива. Переменным примитивных типов, таких, как int, char (символ), float (с плавающей точкой) и double (с удвоенной точностью) присваивается нуль. Элементам, указывающим на управляемые объекты, также по умолчанию присваивается нулевое значение (т.е. нулевой указатель). Элементы значимых типов инициализируются с помощью их принятого по умолчанию конструктора (т.е. конструктора, не имеющего аргументов). Значимые типы подробнее рассмотрены ниже.
В следующем примере иллюстрируется работа с массивами, и сравниваются управляемый двумерный массив и обычный неуправляемый двумерный же массив. Обратите внимание, что при работе с неуправляемым массивом используется старый синтаксис доступа к элементам массива [ ] [ ], тогда как при работе с управляемым массивом, который является истинно двумерным, используется синтаксис [, ]. Хотя в этом примере при использовании синтаксиса [ ] [ ] каждый из подмассивов имеет одинаковое количество элементов, в других случаях они могут иметь разные размеры (т.н. массив с неровным правым краем). Синтаксис [, ] предполагает использование истинно прямоугольного массива.

//Arrayl.срр
fusing <mscorlib.dll>
using namespace System;
// использовать пространство имен Система;
void main () {
// управляемый одномерный массив int
// (использующий сборщик мусора)
Console::WriteLine("managed ID array of int");
// ("управляемый одномерный массив int");
int intArray _gc[]= new int _gc[5];
for (int i=0; i<intArray->Length; i++)
{
intArray[i] = i;
Console::Write(intArray[i]); // Запись
Console::Write("\t"); // Запись } Console::WriteLine();
// управляемый двумерный массив Строк
// (использующий управляемый тип)
Console::WriteLine("managed 2D array of Strings");
// ("управляемый двумерный массив Строк ");
String *str2DArray[,] = new String *[2,3]; // новая Строка
for(int row=0; row<str2DArray->GetLength(0); row++)
//по строкам
{
for(int col=0; col<str2DArray->GetLength(l) ; col++)
//по столбцам
{
str2DArray[row,col] = (row*10 + col).ToString();
// str2DArray [строка, столбец] = (row*10 + столбец)
// .ToString ();
Console::Write(str2DArray[row,col]);
// Запись:: (str2DArray [строка, столбец]);
Console::Write("\t"); // Запись }
Console::WriteLine(); }
// неуправляемый двумерный массив int (для сравнения)
Console::WriteLine("unmanaged 2D array of int");
// ("неуправляемый двумерный массив int");
int int2DArray[2][3];
for(int row=0; row<2; row++) //по строкам
{
for (int col=0; col<3; col++) // по столбцам {
int2DArray[row][col] = row*10 + col;
// int2DArray [строка] [столбец] = row*10 + столбец; Console::Write(int2DArray[row][col]); // Запись:: (int2DArray [строка] [столбец]); Console::Write("\t"); // Запись }
Console::WriteLine(); } )

Результат работы программы приведен ниже. Управляемый прямоугольный двумерный массив содержит элементы типа String*, а неуправляемый — элементы типа int. Однако управляемый массив может также содержать и элементы неуправляемых типов, между тем как неуправляемый массив — лишь элементы неуправляемых типов.

managed ID array of int 01234 managed 2D array of Strings 012 10 11 12
unmanaged 2D array of int
0 1 2
10 11 12

Перевод такой:

управляемый одномерный массив int
01234
управляемый двумерный массив Строк
0 1 2
10 11 12
неуправляемый двумерный массив int
0 1 2
10 11 12

Приведем еще один пример, в котором сравнивается использование массива массивов (синтаксис [ ] [ ]) и прямоугольного двумерного массива (синтаксис [, ]). На этот раз, ради более корректного сравнения, оба массива содержат элементы типа int.

//Array2.срр
#using <mscorlib.dll>
using namespace System;
// использовать пространство имен Система;
void main(void) {
Console::WriteLine("Rectangular array using [,]");
// ("Использование прямоугольного массива [,] ");
int rect2DArray [,] = new int _gc [3,41; // сборщик мусора -
// управляемый
for(int row=0; row< rect2DArray ->GetLength(0); row++) // по строкам {
for(int col=0; col< rect2DArray->GetLength(1); col++)
// по столбцам
{
rect2DArray [row,col] = row*10 + col; // rect2DArray [строка, столбец] = row*10 + столбец; Console : -.Write (rect2DArray [row, col] ) ; // Запись:: (rect2DArray [строка, столбец]); Console::Write("\t"); // Запись }
Console::WriteLine(); }
Console::WriteLine("Array of arrays using [][]"); // ("использование массива массивов [] [] "); int arrayOfArray[3][4]; // неуправляемый for(int row=0; row<3 ; row++) // по строкам {
for(int col=0; col<4; col++) // по столбцам {
arrayOfArray[row][col] = row*10 + col;
Добавлен редактором русского перевода. — Прим. ред.
// arrayOfArray [строка] [столбец] = row*10 + столбец; Console::Write(arrayOfArray[row][col]); // Запись:: (arrayOfArray [строка] [столбец]); Console::Write("\t"); // Запись
}
Console::WriteLine(); } >

Программа напечатает:

Rectangular array using [,]
0 1 2 3
10 11 12 13
20 21 22 23
Array of arrays using [][]
0 1 2 3
10 11 12 13
20 21 22 23

Перевод такой:

Использование прямоугольного массива []
0 1 2 3
10 11 12 13
20 21 22 23
Использование массива массивов [] []
0 1 2 3
10 11 12 13
20 21 22 23

На рис. 3.1 и 3.2 показано размещение в памяти элементов массива массивов (объявленного с помощью синтаксиса [ ] [ ]) и прямоугольного двумерного массива (объявленного с помощью синтаксиса [, ]), использовавшихся в предыдущем примере.