CHAPTER 16 Arrays in C#

Arrays in C# are reference objects; they’re allocated out of heap space rather than on the stack. The elements of an array are stored as dictated by the element type; if the element type is a reference type (such as string), the array will store references to strings. If the element is a value type (such as a numeric type or a struct type), the elements are stored directly within the array. In other words, an array of a value type doesn’t contain boxed instances.

You can declare arrays using the following syntax:

<type>[] identifier;

The initial value of an array is null. You can create an array object using new:

int[] store = new int[50];

string[] names = new string[50];

When an array is created, it initially contains the default values for the types that are in the array. For the store array, each element is an int with the value 0. For the names array, each element is a string reference with the value null.

1. Array Initialization

You can initialize arrays at the same time as you create them. During initialization, you can omit new int[x], and the compiler will determine the size of the array to allocate from the number of items in the initialization list:

int[] store = {0, 1, 2, 3, 10, 12};

The preceding line is equivalent to this:

int[] store = new int[6] {0, 1, 2, 3, 10, 12};

2. Multidimensional and Jagged Arrays

To index elements in more than one dimension, you can use either a multidimensional array or a jagged array.

2.1. Multidimensional Arrays

Multidimensional arrays have more than one dimension:

int[,] matrix = new int[4, 2];

matrix[0, 0] = 5;

matrix[3, 1] = 10;

The matrix array has a first dimension of 4 and a second dimension of 2. This array could be initialized using the following statement:

int[,] matrix = { {1, 1}, {2, 2}, {3, 5}, {4, 5}};

The matrix array has a first dimension of 5 and a second dimension of 2. Multidimensional arrays are sometimes called rectangular arrays because the elements can be written in a rectangular table (for dimensions less than 2). When the matrix array is allocated, a single chunk is obtained from the heap to store the entire array (see Figure 16-1).

The following is an example of using a multidimensional array:

using System; class Test {

public static void Main()

{

int[,] matrix = { {1, 1}, {2, 2}, {3, 5}, {4, 5}, {134, 44} };

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

{

for (int j = 0; j < matrix.GetLength(1); j++)

{

Console.WriteLine(“matrix[{0}, {1}] = {2}”, i, j, matrix[i, j]);

}

}

}

}

The GetLength() member of an array will return the length of that dimension. This example produces the following output:

matrix[0, 0] = 1

matrix[0, 1] = 1

matrix[l, 0] = 2

matrix[l, l] = 2

matrix[2, 0] = 3

matrix[2, l] = 5

matrix[3, 0] = 4

matrix[3, 1] = 5

matrix[4, 0] = 134

matrix[4, 1] = 44

2.2. Jagged Arrays

A jagged array is merely an array of arrays and is called jagged because it doesn’t have to be rectangular. For example:

int[][] matrix = new int[3][];

matrix[0] = new int[5];

matrix[1] = new int[4];

matrix[2] = new int[2];

matrix[0][3] = 4;

matrix[1][1] = 8;

matrix[2][0] = 5;

The matrix array here has only a single dimension of three elements. Its elements are integer arrays. The first element is an array of five integers, the second is an array of four integers, and the third is an array of two integers (see Figure 16-2). The matrix variable is a reference to an array of three references to arrays of integers. Four heap allocations were required for this array.

Using the initialization syntax for arrays, you could write the following:

using System; class Test {

public static void Main()

{

int[][] matrix = {new int[5], new int[4], new int[2] };

matrix[0][3] = 4;

matrix[1][1] = 8;

matrix[2][0] = 5;

for (int i = 0; i < matrix.Length; i++)

{

for (int j = 0; j < matrix[i].Length; j++)

{

Console.WriteLine(“matrix[{0}, {1}] = {2}”, i, j, matrix[i][j]);

}

}

}

}

Note that the traversal code is different from the multidimensional case. Because matrix is an array of arrays, you need to use a nested single-dimensional traverse.

3. Arrays of Reference Types

Arrays of reference types can be somewhat confusing because the elements of the array are initialized to null rather than to the element type. For example:

class Employee {

public void LoadFromDatabase(int employeeID)

{

// load code here

}

}

class Test {

public static void Main()

{

Employee[] emps = new Employee[3];

emps[0].LoadFromDatabase(15);

emps[1].LoadFromDatabase(35);

emps[2].LoadFromDatabase(255);

}

}

When LoadFromDatabase() is called, a null exception will be generated because the elements referenced have never been set and are therefore still null.

You can rewrite the class as follows:

class Employee {

public static Employee LoadFromDatabase(int employeelD)

{

Employee emp = new Employee();

// load code here return(emp);

}

}

class Test {

public static void Main()

{

Employee[] emps = new Employee[3];

emps[0] = Employee.LoadFromDatabase(15);

emps[1] = Employee.LoadFromDatabase(35);

emps[2] = Employee.LoadFromDatabase(255);

}

}

This allows you to create an instance, load it, and then save it into the array.

The reason that arrays aren’t initialized is for performance. If the compiler did do the initialization, it’d need to do the same initialization for each element, and if that wasn’t the right initialization, all those allocations would be wasted.

4. Array Conversions

Conversions are allowed between arrays based on the number of dimensions and the conver­sions available between the element types.

An implicit conversion is permitted from array S to array T if the arrays have the same number of dimensions, if the elements of S have an implicit reference conversion to the element type of T, and if both S and T are reference types. In other words, if an array of class references exists, it can be converted to an array of a base type of the class.

Explicit conversions have the same requirements, except that the elements of S must be explicitly convertible to the element type of T:

using System;

class Test {

public static void PrintArray(object[] arr)

{

foreach (object obj in arr)

Console.WriteLine(“Word: {0}”, obj);

}

public static void Main()

{

string s = “I will not buy this record, it is scratched.”;

char[] separators = {‘ ‘};

string[] words = s.Split(separators);

PrintArray(words);

}

}

In this example, the string array of words can be passed as an object array, because each string element can be converted to object through a reference conversion. This isn’t possible, for example, if there’s a user-defined implicit conversion.

5. The System.Array Type

Because arrays in C# are based on the .NET runtime System.Array type, they can perform several operations that aren’t traditionally supported by array types.

5.1. Sorting and Searching

The ability to sort and search is built into the System. Array type. The Sort() function will sort the items of an array, and the IndexOf(), LastIndexOf(), and BinarySearch() functions are used to search for items in the array. For more information, see Chapter 30.

5.2. Reverse

Calling Reverse() simply reverses all the elements of the array:

using System;

class Test {

public static void Main()

{

int[] arr = {5, 6, 7};

Array.Reverse(arr);

foreach (int value in arr)

{

Console.WriteLine(“Value: {0}”, value);

}

}

}

This produces the following output:

Source: Gunnerson Eric, Wienholt Nick (2005), A Programmer’s Introduction to C# 2.0, Apress; 3rd edition.

Leave a Reply

Your email address will not be published. Required fields are marked *