ArraysOne particular aspect of variable declaration that Chapter 1 didn't cover is array declaration. With array declaration, you can store multiple items of the same type using a single variable and still access them individually using the index when required. In C#, the array index starts at zero. Therefore, arrays in C# are zero based .
Declaring an Array
In C#, you declare arrays using square brackets. First, you specify the type of the items within the array, followed by
Listing 2.28. Declaring an Array
Obviously, the first part of the array identifies the data type of the elements within the array. The square brackets that are part of the declaration identify the rank , or the number of dimensions, for the array; in this case it is an array of rank one. These two pieces form the data type for the variable languages .
Listing 2.28 defines an array with a rank of one. Commas within the square brackets define additional dimensions. Listing 2.29, for example, defines a two-dimensional array of
Listing 2.29. Declaring a Two-Dimensional Array
In Listing 2.29, the array has a rank of two. The first dimension could
Instantiating and Assigning Arrays
Once an array is declared, you can immediately fill its values using a comma-delimited list of items
Listing 2.30. Array Declaration with Assignment
The first item in the comma-delimited list becomes the first item in the array; the second item in the list becomes the second item in the array, and so on. The curly brackets are the notation for defining an array literal. The assignment syntax shown in Listing 2.30 is available only if you declare and assign the value within one statement. To assign the value after declaration requires the use of the keyword new and the corresponding data type, as shown in Listing 2.31. Listing 2.31. Array Assignment Following Declaration
C# also allows use of the new keyword as part of the declaration statement, so it allows the assignment and the declaration shown in Listing 2.32. Listing 2.32. Array Assignment with new during Declaration
The use of the
new
keyword
Whenever you use the
new
keyword as part of an array assignment, you may also specify the size of the array within the square brackets. Listing 2.33
Listing 2.33. Declaration and Assignment with the new Keyword
The array size in the initialization statement and the number of elements contained within the curly braces must match. Furthermore, it is possible to assign an array but not specify the initial values of the array, as demonstrated in Listing 2.34. Listing 2.34. Assigning without Literal Values
Assigning an array but not initializing the initial values will still initialize each element. The runtime initializes elements to their default values, as
As a result, it is not necessary to individually assign each element of an array before using it. In C# 2.0, it is possible to use the default() operator to determine the default value of a data type. default() takes a data type as a parameter. default(int) , for example, returns and default(char) returns \0 . Because the array size is not included as part of the variable declaration, it is possible to specify the size at runtime. For example, Listing 2.35 creates an array based on the size specified in the Console.ReadLine() call. Listing 2.35. Defining the Array Size at Runtime
C# initializes multidimensional arrays similarly. A comma separates the size of each rank. Listing 2.36 initializes a tic-tac-toe board with no moves. Listing 2.36. Declaring a Two-Dimensional Array
Initializing a tic-tac-toe board with a specific position instead could be done as shown in Listing 2.37. Listing 2.37. Initializing a Two-Dimensional Array of Integers
The initialization follows the pattern in which there is an array of three elements of type int[] , and each element has the same size; in this example, the size is three. Note that the dimension of each int[] element must be identical. The declaration shown in Listing 2.38, therefore, is not valid. Listing 2.38. A Multidimensional Array with Inconsistent Size, Causing an Error
Representing tic-tac-toe does not require an integer in each position. One alternative is a separate virtual board for each player, with each board containing a
bool
that indicates which
Listing 2.39. Initializing a Three-Dimensional Array
In this example, the board is initialized and the size of each rank is explicitly identified. In addition to identifying the size as part of the
new
expression, the literal values for the array are provided. The literal values of type
bool[,,]
are broken into two arrays of type
bool[,]
, size 3x3. Each two-dimensional array is
As already mentioned, each dimension in a multidimensional array must be consistently sized. However, it is also possible to define a jagged array , which is an array of arrays. Jagged array syntax is slightly different from that of a multidimensional array, and furthermore, jagged arrays do not need to be consistently sized. Therefore, it is possible to initialize a jagged array as shown in Listing 2.40. Listing 2.40. Initializing a Jagged Array
A jagged array doesn't use a comma to identify a new dimension. Rather, a jagged array defines an array of arrays. In Listing 2.40, [] is placed after the data type int[] , thereby declaring an array of type int[] . Notice that a jagged array requires an array instance for each internal array. In this example, you use new to instantiate the internal element of the jagged arrays. Leaving out the instantiation would cause a compile error. Using an Array
You access a specific item in an array using the square
Listing 2.41. Declaring and Accessing an Array
The square bracket notation is also used to store data into an array. Listing 2.42 switches the order of "C++" and "Java" . Listing 2.42. Swapping Data between Positions in an Array
For multidimensional arrays, an element is identified with an index for each dimension, as shown in Listing 2.43. Listing 2.43. Initializing a Two-Dimensional Array of Integers
Jagged array element assignment is slightly different because it is consistent with the jagged array declaration. The first element is an array within the array of arrays. The second index specifies the item within the selected array element (see Listing 2.44). Listing 2.44. Declaring a Jagged Array
LengthYou can obtain the length of an array, as shown in Listing 2.45. Listing 2.45. Retrieving the Length of an Array
Arrays have a fixed length; they are bound such that the length cannot be changed without re-creating the array. Furthermore, overstepping the bounds (or length) of the array will cause the runtime to report an error. This can occur by accessing (either retrieving or assigning) the array with an index for which no element exists in the array. Such an error frequently occurs when you use the array length as an index into the array, as shown in Listing 2.46. Listing 2.46. Accessing Outside the Bounds of an Array, Throwing an Exception
Note The Length member returns the number of items in the array, not the highest index. The Length member for the languages variable is 9 , but the highest index for the languages variable is 8 . It is a good practice to use Length in place of the hardcoded array size. To use Length as an index, for example, it is necessary to subtract 1 to avoid an out-of-bounds error (see Listing 2.47).
Listing 2.47. Using Length - 1 in the Array Index
To avoid overstepping the bounds on an array use Length - 1 , as demonstrated in Listing 2.47, in place of a hardcoded value accessing the last item in the array. Length returns the total number of elements in an array. Therefore, if you had a multidimensional array such as bool cells[,,] of size 2·3·3, Length would return the total number of elements, 18.
More Array
|
class ProgrammingLanguages { static void Main() { string [] languages = new string []{ "C#", "COBOL", "Java", "C++", "Visual Basic", "Pascal", "Fortran", "Lisp", "J#"}; System.Array.Sort(languages); searchString = "COBOL"; index = System.Array.BinarySearch( languages, searchString); System.Console.WriteLine( "The wave of the future, {0}, is at index {1}.", searchString, index); System.Console.WriteLine(); System.Console.WriteLine("{0,-20}\t{1,-20}", "First Element", "Last Element"); System.Console.WriteLine("{0,-20}\t{1,-20}", "-------------", "------------"); System.Console.WriteLine("{0,-20}\t{1,-20}", languages[0], languages[languages.Length-1]); System.Array.Reverse(languages); System.Console.WriteLine("{0,-20}\t{1,-20}", languages[0], languages[languages.Length-1]); // Note this does not remove all items from the array. // Rather it sets each item to the type's default value. System.Array.Clear(languages, 0, languages.Length); System.Console.WriteLine("{0,-20}\t{1,-20}", languages[0], languages[languages.Length-1]); System.Console.WriteLine( "After clearing, the array size is: {0}", languages.Length); } } |
The results of Listing 2.48 are shown in Output 2.19.
The wave of the future, COBOL, is at index 1. First Element Last Element ------------- ------------ C# Visual Basic Visual Basic C# After clearing, the array size is: 9 |
Access to these methods is on the System.Array class. For the most part, using these methods is self-explanatory, except for two noteworthy items.
Before using the BinarySearch() method, it is important to sort the array. If values are not sorted in increasing order, then the incorrect index may be returned. If the search element does not exist, then the value returned is negative. (Using the complement operator, ~index , returns the first index, if any, that is larger than the searched value.)
The Clear() method does not remove elements of the array and does not set the length to zero. The array size is fixed and cannot be modified. Therefore, the Clear() method sets each element in the array to its default value ( false , , or null ). This explains why Console.WriteLine() creates a blank line when writing out the array after Clear() is called.
Language Contrast: Visual BasicRedimensioning ArraysVisual Basic includes a Redim statement for changing the number of items in an array. Although there is no equivalent C# specific keyword, there is a method available in .NET 2.0 that will re-create the array and then copy all the elements over to the new array. The method is called System.Array.Resize . |
Like strings, arrays have instance
Retrieving the length of a particular dimension does not require the Length property. To retrieve the size of a particular rank, an array includes a GetLength() instance method. When calling this method, it is necessary to specify the rank whose length will be returned (see Listing 2.49).
bool [,,] cells; cells = new bool [2,3,3]; System.Console.WriteLine( cells.GetLength(0) ); // Displays 2 |
The results of Listing 2.49 appear in Output 2.20.
2 |
Listing 2.49 displays 2 because this is the number of elements in the first dimension.
It is also possible to retrieve the entire array's rank by accessing the array's Rank member. cells.Rank , for example, will return 3 .
By default, assigning one array variable to another copies only the array reference, not the individual elements of the array. To make an entirely new copy of the array, use the array's Clone() method. The Clone() method will return a copy of the array; changing any of the members of this new array will not affect the members of the original array.
Variables of type
string
are accessible like an array of
string [] args; ... if (args[0][0]=='-') { // This parameter is an option } |
This snippet uses the
if
statement, which is covered in Chapter 3. In addition, it
string [] args; ... string arg = args[0]; if (arg[0] == '-') { // This parameter is an option } |
Not only can string characters be accessed individually using the array accessor, it is also possible to retrieve the entire string as an array of characters using the string's ToCharArray() method. Using this method, you could reverse the string using the System.Array.Reverse() method, as demonstrated in Listing 2.52, which determines if a string is a palindrome.
class Palindrome { static void Main() { string reverse, palindrome; char [] temp; System.Console.Write("Enter a palindrome: "); palindrome = System.Console.ReadLine(); // Remove spaces and convert to lowercase reverse = palindrome.Replace(" ", ""); reverse = reverse.ToLower(); // Convert to an array temp = reverse.ToCharArray(); // Reverse the array System.Array.Reverse(temp); // Convert the array back to a string and // check if reverse string is the same. if (reverse == new string(temp)) { System.Console.WriteLine("\"{0}\" is a palindrome.", palindrome); } else { System.Console.WriteLine( "\"{0}\" is NOT a palindrome.", palindrome); } } } |
The results of Listing 2.52 appear in Output 2.21.
Enter a palindrome:
NeverOddOrEven
"NeverOddOrEven" is a palindrome.
|
This example uses the
new
keyword; this time, it creates a new string from the
This section introduced the three different types of arrays:
|
Common Mistake |
Error Description |
Corrected Code |
|---|---|---|
|
int
numbers[];
|
The square braces for declaring an array appear after the data type, not after the variable identifier. |
int
[] numbers;
|
|
int
[] numbers;
numbers = {42, 84, 168 };
|
When assigning an array after declaration, it is necessary to use the new keyword and then specify the data type. |
int [] numbers; numbers = -new -int []{ 42, 84, 168 } |
|
int
[3] numbers =
{ 42, 84, 168 };
|
It is not possible to specify the array size as part of the variable declaration. |
int
[] numbers =
{ 42, 84, 168 };
|
|
int [] numbers = new int []; |
The array size is required at initialization time unless an array literal is provided. |
int [] numbers = new int [3]; |
|
int [] numbers = new int [3]{} |
The array size is specified as 3 , but there are no elements in the array literal. The array size must match the number of elements in the array literal. |
int [] numbers = new int [3] { 42, 84, 168 }; |
|
int [] numbers = new int [3]; Console.WriteLine( numbers[3]); |
Array indexes start at zero. Therefore, the last item is one less than the array size. (Note that this is a runtime error, not a compile-time error.) |
int [] numbers = new int [3]; Console.WriteLine( numbers[2]); |
|
int [] numbers = new int [3]; numbers[numbers.Length] = 42; |
Same as previous error: 1 needs to be subtracted from the Length to access the last element. (Note that this is a runtime error, not a compile-time error.) |
int [] numbers = new int [3]; numbers[numbers.Length-1] = 42; |
|
int
[] numbers;
Console.WriteLine(
numbers[0]);
|
numbers
has not yet been assigned an
|
int
[] numbers = {42, 84};
Console.WriteLine(
numbers[0]);
|
|
int
[,] numbers =
{ {42},
{84, 42} };
|
Multidimensional arrays must be structured consistently. |
int
[,] numbers =
{ {42, 168},
{84, 42} };
|
|
int
[][] numbers =
{ {42, 84},
{84, 42} };
|
Jagged arrays require instantiated arrays to be specified for the arrays within the array. |
int [][] numbers = { new int []{42, 84}, new int []{84, 42} }; |