BlackWasp
C# Programming
.NET 1.1

C# Arrays

The twenty-eighth part of the C# Fundamentals tutorial increases our knowledge of data types.  The tutorial has reviewed many data types, each storing a single value.  This article considers the use of arrays to store many values in a simple structure.

What is an Array?

So far in the C# Fundamentals tutorial we have concentrated on the basic data types that are available to the developer.  In each case, the data type stored a single value.  Often it is necessary to group together related values that represent a series of data, tabular data or more complex structures.  One of the methods by which this can be achieved is by creating an array.

An array is simply a collection of variables that share a common name and data type.  The data type can be any type supported by the .NET framework including strings, numeric types and objects.  The items in an array are distinguished from one another by one or more index numbers.  This allows easy control of the linked values.

The .NET framework implements all arrays as objects.  This does not mean that the individual elements need to be objects but it does affect the methods in which arrays can be manipulated.  For example, an array must be instantiated using the new keyword.  An array may also be left uninitialised and therefore containing a null value.

Simple Array Declaration

The most basic type of array is known as a one-dimensional array.  This structure provides a simple list of numbered variables.  The method used to declare the array is similar to that of any other variable.  However, the data type in the declaration is followed by a pair of square brackets.  The following example creates an array of integers.

int[] listItems;

Once declared in this manner, the array contains a null value.  We can now instantiate the array using the new keyword and indicating the number of items that we require in the list.  By adding the following code to the example above, the array is generated with ten items.

listItems = new int[10];

As with previous declarations, the two elements can be combined into a single line of code:

int[] listItems = new int[10];

Index Numbering

When an array is created, C# always starts its index numbering with item zero.  The index number increments with each subsequent item.  In the above example, the array generated includes ten items numbered from zero to nine.  Each item can be used as an individual variable by specifying the variable name followed by the index number between square brackets.  It is important to note that the boundaries of the array are strictly enforced.  Any attempt to read or modify a value outside of the declared range cause an exception.

int[] listItems = new int[3];

listItems[0] = 25;
listItems[1] = listItems[0] * 2;    // listItem[1] = 50
listItems[2] = listItems[1] * 2;    // listItem[2] = 100
listItems[3] = listItems[2] * 2;    // Causes an exception

Initialising an Array

As demonstrated, each element in an array can be accessed individually.  This can be tedious when initialising an array to a specific set of values and requires excessive amounts of coding.  Luckily, C# provides a method to initialise all of the array variables in a single statement.  The comma-separated list of values is simply entered within a pair of braces and assigned to the declaration.  The number of items in the array need not be specified as the compiler can determine this automatically.

int[] listItems = new int[] {2,4,8};

int value = listItems[0];           // value = 2

Retrieving an Array's Length

It is possible that the size of an array to be processed is unknown.  To ensure that the boundaries of the array are not exceeded during processing, it is important to be able to determine the array's length.  This can be retrieved using the Length property of the array object.  When reading a property of an entire array, the square brackets are omitted.

int[] listItems = new int[] {2,4,8};

int length = listItems.Length;         // length = 3

Two-Dimensional Arrays

The simple "list" type of array described above is called a one-dimensional array; the single dimension being traversed using the index number.  It is possible to use more than one dimension in an array to create more complex structures.  A two-dimensional array can be used to hold a table of values.  In the next example, we will create an array to hold the following table of string values.  The numbered rows and columns indicate the index numbers for each dimension for each item:

Index0123
0AppleBananaClementineDamson
1ElderberryFigGrapeHuckleberry
2Indian PruneJujubeKiwiLime

The table can be represented in an array with two dimensions.  The first dimension will traverse the row numbers and the second dimension the columns.  To declare such an array a comma is required in the initial data type definition and the two dimension boundaries are included in the square brackets.  The same notation is used to access the individual variables.

string[,] table = new string[3,4];

table[0,0] = "Apple";
table[0,1] = "Banana";
table[0,2] = "Clementine";
table[0,3] = "Damson";
table[1,0] = "Elderberry";
table[1,1] = "Fig";

// ...and so on

Initialising a Two-Dimensional Array

With tabular data, the initialisation of the array variables can require many lines of code.  Again, an initialisation method is available to minimise the code required.  Each row of the table is initialised with a comma-separated list of values within a pair of braces.  These rows are then also comma-separated and surrounded by a further pair of braces.  The following example shows this in action, initialising the entire table from the previous section.  The code is separated into several lines for readability.  Note the use of the commas in the declaration to warn the compiler that two dimensions are in use.

string[,] table = new string[,] {
    {"Apple", "Banana", "Clementine", "Damson"},
    {"Elderberry", "Fig", "Grape", "Huckleberry"},
    {"Indian Prune", "Jujube", "Kiwi", "Lime"}
};

string fruit = table[1,3];              // fruit = "Huckleberry"

Multidimensional Arrays

Arrays can contain any number of dimensions to allow for more complex data structures.  To add extra dimensions to an array, the declaration simply includes extra commas.  The initialisation of an array becomes more complex with further nested, comma-separated lists of lists.  However, when such complex structures are used, they are generally initialised programmatically or using information from a database.

int[,,] cube = new int[5, 4, 10];
int[,,,,] fiveDimensional = new int[5, 4, 10, 20, 6];

Retrieving a Multidimensional Array's Size

The size of a multidimensional array can be requested in two different manners.  The Length property returns the number of individual variables of the entire array.  This is equal to the product of the sizes of every dimension.

int[,,] cube = new int[5,4,10];

int length = cube.Length;               // length = 200

The length of a multidimensional array can be a useful number.  However, this does not tell us everything we may wish to know about an array.  We may also need to determine the number of dimensions that an array contains and the length of each of those dimensions.  The Rank property of the array object returns an integer containing the former.  For the latter, the GetLength property is used with a parameter indicating the number of the dimension to query.

int[,,] cube = new int[5,4,10];

int dimensions = cube.Rank;             // dimensions = 3
int length0 = cube.GetLength(0);        // length0 = 5
int length1 = cube.GetLength(1);        // length1 = 4
int length2 = cube.GetLength(2);        // length2 = 10

Jagged Arrays

Earlier in the article a two-dimensional array was used to hold a table of data.  This type of array is also known as rectangular as it generates a rectangular table.  Sometimes it is useful to create a two-dimensional array that is not perfectly rectangular and, in fact, has rows of varying lengths.  Consider the following table:

Index0123
0AppleBananaClementine
1CabbageLettuceOnionPotato
2CheeseMilk

This table contains three rows of data but each row contains a different number of columns.  C# provides a method to represent this structure in a special type of array known as a jagged array.  In fact, a jagged array is actually a nested array of arrays, declared using two pairs of square brackets rather than a single pair with two dimension sizes.   Only the number of rows is specified in the initial declaration; the individual rows are sized or initialised individually.

string[][] table = new string[3][];         // Declare the main array

// Declare each sub-array (row lengths)
table[0] = new string[] {"Apple", "Banana", "Clementine"};
table[1] = new string[] {"Cabbage", "Lettuce", "Onion", "Potato"};
table[2] = new string[] {"Cheese", "Milk"};

// Test some values
string fruit = table[0][2];             // fruit = "Clementine"
string dairy = table[2][1];             // dairy = "Milk"

Assigning and Copying Arrays

Arrays are Reference Types

In a previous instalment of the C# Fundamentals tutorial reference types were mentioned.  All objects, including arrays, are reference types. This means that the data in the object is stored somewhere in the computer's memory and the variable holds a pointer to that area of memory.  If one object variable is assigned to another, only the pointer to the memory location is duplicated; both variables actually point to the same data.  A change in one object's values is therefore reflected in the other object.

This can be demonstrated by assigning one array to another.  A change to any of the elements of either array is visible in both:

int[] primary = new int[] {2,4,8};

// Point a second array at the same memory range using assignment
int[] secondary = primary;

// Retrieve a value from the primary array
int value = primary[1];                 // value = 4

// Alter the value in the secondary array and re-read the primary
secondary[1] = 99;
value = primary[1];                     // value = 99

It is important to understand the effects of assigning reference types as mistakenly modifying one instance can unexpectedly cause problems elsewhere.

Cloning Arrays

It is often necessary to create a copy of an array that may be manipulated without damaging the contents of the original.  To achieve this, the array class includes a Clone method.  Rather than assigning a simple reference, this creates a completely new copy of the array.  The Clone method returns an object but the specific array type is not specified so this object must be cast to the correct type for assignment.

int[] primary = new int[] {2,4,8};

// Clone the array into a secondary array, casting appropriately
int[] secondary = (int[])primary.Clone();

// Retrieve a value from the primary array
int value = primary[1];                 // value = 4

// Alter the value in the secondary array and re-read the primary
secondary[1] = 99;
value = primary[1];                     // value = 4
value = secondary[1];                   // value = 99
Link to this Page12 January 2007
RSS RSS Feed
74 users on-line