An array is a fixed-sized data structure for organizing and accessing elements of the same type. The Array class in C# is in the System namespace. Arrays are similar to classes like Queue and Stack in the System.Collection namespace. And, Arrays are considered collections since the class inherits the IList interface (more on interfaces later). Unlike in C and C++, arrays are not simply sections of contiguous memory but are objects and therefore have properties and methods. See here for a complete listing of properties and methods of the .NET Array class. If we only needed to work with a few variables at a time, like num1, num2, and num3, then arrays would be of minimal value. However, if we have seven, 70, 7000, or more elements, then working with arrays is extremely beneficial. For example, suppose we are recording population data for each of the 50 U.S. states. If we were limited to primitive types, then we would have 50 variables named something like popState1 through popState50. With an array, we can contain all 50 elements within one array named popState.
In this chapter we will consider three array types: one-dimensional, multi-dimensional, and jagged. We will also review a few of the methods provided by the C# Array Class.
The one-dimensional array is the simplest and most common type. It provides convenient ways to declare, define, and initialize multiple data items. Note: the terms declare and define are quite similar and are often used interchangeably. However, for the purposes of this tutorial, I will employ classical definitions. That is, declare means to name a variable and define means to allocate memory. Recall that for primitive types, the declaration and definition occurs at the same time. This is usually the case for arrays. With arrays, the declaration and definition can occur separately but the size of the array must be supplied before the array can be used. After an array is declared, before it can be used it must be defined either explicitly using the keyword
new with a size declarator or implicitly via an initialization list.
On line 15 a one-dimensional array capable of holding three integers is created named oneDimArray1. The square bracket symbols  are the array operators. The
new keyword is used to create an object of the specified type. In the case of line 15, we are requesting that an object of type array be created with memory for three integers. We can separate the operations occurring on line 15. Lines 41 and 42 separate the declaration and definition operations. Line 41 names the array and line 42 allocates three integers for the size.
Lines 17-19 show the array elements (each array member) being assigned values. Arrays are
zero-based which means that the first member is accessed with a "0" index, the second member is accessed with an index of "1", etc. Indexes are also known as subscripts. In the image below, three locations in memory are created for the array named oneDimArray1. The sample address numbers are presented as hexadecimal (16-base) numbers. Notice how the address values are incremented by 4 (from 1 to 5 to 9). Recall that 4 is the byte size of an integer. After lines 17-19 the values stored in those addresses are 1, 2, and 3. Also note the highlighted index values of 0, 1, and 2 which are used to access the memory locations.
Lines 31 and 38 provide alternative ways of creating and initializing an array. On both lines 31 and 38 an array of three integers is created and initialized with the values 1, 2, and 3. The size of oneDimArray3 is implicitly obtained from the number of arguments in the initialization list. When an array is implicitly sized, a size declarator is not required but there is a benefit to including it.
The highlighted "2" in the code segment below is called the size declarator. While not required if an initialization list is supplied, the "2" does provide an extra check. It ensures that the size declarator and the number of arguments in the initialization list agree. For example, the sizeCheckerArray has an expected length of two but the initialization list contains three elements. A compile time (first-level compilation) error is generated if the size declarator does not agree with the number of arguments in the initialization list.
Line 38 not only declares and defines the array it also initializes the array contents. So, lines 31 and 348 each do the work of lines 15-19. Line 38 is the most compact version. To obtain the extra check and to make the code more readable, a size declarator can be supplied along with an initialization list. That would be like line 31 but including a size declarator.
C# arrays can also be multi-dimensional. Two-dimensional (two-dim) arrays are the most common multi-dimensional arrays. It is natural to view a two-dim array as a table as shown. Notice the indexes that are used to access each element. There are two rows (Row 0 and Row 1) and three columns ( Col 0, Col 1, Col 2).
The elements in the table correspond to those shown on lines 47-52. On line 45 a two-dim array of doubles is created with two rows and three columns. Lines 47-52 assign the values of the array on the right to the indexes on the left. Lines 64 and 65 accomplish the same thing as lines 45-52. Lines 64 and 65 could be combined into one line but are often written across multiple lines to provide a visual representation of the data. Notice how the initialization list emulates the data values in the table.
The last form of array we will consider is a jagged array which is called that for its uneven construction. The table below depicts the jagged array that is first created on line 68. That line of code only creates two arrays within the jagged array but does not size them. The two arrays are sized and populated with data on lines 66 and 67. The first of the two arrays contains three elements and the second array contains five elements. This uneven characteristic is why the array is referred to as jagged. If both arrays within the jagged array were the same size then they could be represented as a multi-dimensional array.
Line 68 creates a jagged array. Note that unlike the multi-dimensional array with a comma in the array operators , the jagged array has two sets of array operators side-by-side. On line 68 a jagged array is created which can be read as, "Create two arrays of integers within the jagged array and the size of both to be specified later." Line 71 and 72 specify the sizes of each array and data values.
Unlike C and C++, C# includes a feature known as array bounds checking. That is, if the program attempts to access an element that is out-of-range of the array, an exception (runtime error) is produced. To demonstrate this particular type of error, the "2" index on line 78 was changed to a "3". The program compiled but produced a runtime IndexOutOfRangeException when it was executed. The code attempted to access Element 3 of Array 0 which does not exist per the table above.
We will learn how to handle exceptions with try-catch-finally blocks in an upcoming chapter. However, it should be noted that errors like IndexOutOfRangeExceptions are known as "unchecked errors" and should not be handled with a try-catch-finally block. Rather, unchecked errors should be prevented by checks in the code. For instance, in the code segment below, the value of arrayIndex is checked to ensure it is within the appropriate range before being used subsequently in the array.
The Array class has a variety of properties and methods here. Since each array we create inherits from the Array class, our arrays have multiple properties and methods available. For example, on line 89 we use the Array.Sort() method to sort the contents of the mixedArray. The original content is randomly arranged but after calling Array.Sort(), mixedArray is sorted. And, on line 104 we use the Length property to return the length of the mixedArray which is now sorted.
Some of the other useful methods of the Array class are: BinarySearch(), Clone(), Copy(), IndexOf(), Reverse(), and ToString().
The array is a common and very useful data structure in computing. We use arrays a number of times in upcoming chapters. Students should practice working with arrays to obtain a substantial level of familiarity.
Recall that the three primary constructs in all of programming are: sequence, selection, repetition. In the next chapter, we will begin using repetition in our code.