Using Arrays

An array is a collection of objects, all of the same type (all ints, all strings, and so on). Arrays are also indexed, meaning that the language provides a way for you to say “Get me the third item in the array.” Indexing also means that the items in the array are stored in a specific order, which further means that you can loop through the contents of the array in order. That process is called iteration, and we’ll show you how to do it in a minute. Arrays are a standard feature of almost all modern languages, and C# provides built-in syntax for declaring and using arrays.

Arrays are a bit tricky to visualize at first—a bunch of objects occupying the space of a single object. To picture a basic array (also called a one-dimensional array—you’ll see why it’s called that shortly), imagine a series of mailboxes, all lined up one after the other, as shown in Figure 10-1. Each mailbox can hold exactly one object in C#. Each mailbox also has a number (an address in the real world; an index in C#), so you can identify which item is in which box. Unlike real-world mailboxes, though, all the mailboxes must hold the same kind of object; you declare the type of object that the mailboxes will hold when you declare the array.

An array of five integers. Each “mailbox” is one item in the array, which has its own address (the index), and can hold exactly one object.

Figure 10-1. An array of five integers. Each “mailbox” is one item in the array, which has its own address (the index), and can hold exactly one object.

The important thing about arrays is that you can treat the entire array (the set of mailboxes) as a single entity, with a single name. As you’ll see, using loops, you can easily perform an operation on each element within an array in turn.

Declaring Arrays

The syntax for arrays uses the square bracket characters []. For starters, you declare a C# array with the following syntax:

type[] array name;

For example:

int[] myIntArray;

Tip

As usual, you are not actually declaring an array. Technically, you are declaring a variable (myIntArray) that will hold a reference to an array of integers. As always, we’ll use the shorthand and refer to myIntArray as the array, knowing that we really mean it is a variable that holds a reference to an (unnamed) array.

The square brackets tell the C# compiler that you are declaring an array, and the type specifies the type of the elements it will contain. In the previous example, myIntArray is an array of integers.

To instantiate a new array, you use the new keyword. Inside the square brackets, you specify how many elements you want to be in the array. For example:

myIntArray = new int[5];

This statement creates and initializes an array of five integers, all of which are initialized to the value zero.

It is important to distinguish between the array (which is a collection) and the elements held in the array (which can be of any type, as long as all the elements in the array are the same type). myIntArray is the array; its elements are the five integers it holds.

C# arrays are reference types, created on the heap. Thus, the array to which the variable myIntArray refers is allocated on the heap. The elements of an array are allocated based on their own type. Because integers are value types, the elements in myIntArray will be value types, and thus all the elements will be created inside the block of memory allocated for the array. Because an array is a reference type, it will always be passed by reference, even if the elements in the array are value types.

Understanding Default Values

When you create an array of value types, each element initially contains the default value for the type stored in the array (see Table 3-1 in Chapter 3). The statement you saw earlier:

myIntArray = new int[5];

creates an array of five integers, with the value of each set to 0, which is the default value for integer types.

If you create an array of reference types (anything other than the primitive types), those objects are not initialized to their default value. Instead, the references held in the array are initialized to null. If you attempt to access an element in an array of reference types before you have specifically initialized the elements, you will generate an exception.

Suppose you have created a Button class. You’d declare an array of Button objects with the following statement:

Button[] myButtonArray;

and instantiate the actual array like this:

myButtonArray = new Button[3];

You can shorten this to:

Button[] myButtonArray = new Button[3];

This statement does not create an array with references to three Button objects. Instead, this creates the array myButtonArray with three null references. To use this array, you must first create and assign the Button objects for each reference in the array, using the Button class’s constructor as usual. You can construct the objects in a loop that adds them one by one to the array, as you’ll see later in this chapter.

Accessing Array Elements

You can access a single element of an array using square brackets ([]), which are called the index operator. Each element of the array has an index, and you can access the element at a particular index by placing the index number of the element you want inside the brackets. For example, if you have an array of ints, and you want to assign the element with index 3 to another variable, you’d do it like this:

int myInt = myIntArray[3];

There are two things to remember here. The first is that myIntArray[3] isn’t an array; it’s just an int, like any other int. It just happens to be an int that’s an element of an array. The second thing is that myIntArray[3] isn’t the third element in the array—it’s actually the fourth element. Arrays in C# are zero-based, which means that the index of the first element is always zero—in this case, myIntArray[0]. This also means that if you declared myIntArray[] to have five elements, the highest index is 4, not 5. If you try to access myIntArray[5], you’ll get an error. We know this is counterintuitive, but you’ll get used to it quickly enough.

Arrays also have a property called Length, which tells you how many objects the array holds—this is useful, because you won’t always know this when you write your code. Because the indexes start at 0, that means the highest index in an array is always equal to Length - 1. Or to put it another way, arrays are indexed from 0 to Length - 1.

Arrays and Loops

We mentioned earlier that arrays really come into their own when you combine them with loops. Suppose you want to have an array of the first 10 even integers. You need to start with an array of size 10:

int[] myIntArray = new int[10];

Easy enough. Then you need to populate the array with even integers. You can do that with a for loop like this:

for (int i = 0; i < myIntArray.Length; i++)
{
    myIntArray[i] = 2 * (i + 1);
}

Take a closer look at the for loop. The loop control variable i starts at 0, which is also the first element in the array. You want the loop to fill each element in the array, so the condition for ending the loop is i < myIntArray.Length. Remember that myIntArray.Length is going to be 10 in this case, but you want the loop to stop when i is equal to 9. Since i starts at 0, that means the loop will run 10 times. Therefore, it’s important to use <, not <=, in the condition.

Inside the loop, you use myIntArray[i] to iterate through the loop. That is, the first time through, you’ll be setting myIntArray[0]; the next time, myIntArray[1]; and so on. 2 * (i + 1) simply calculates the next even number, and assigns it to the current element of the array. (We used 2 * (i + 1) instead of 2 * i so that the first element in the array would be 2, rather than 0.)

To output the contents of the array to the console, you use a similar loop:

for (int i = 0; i < myIntArray.Length; i++)
{
    Console.WriteLine("Value in index {0} is {1}.", i, myIntArray[i]);
}

Notice that the header of the for loop is exactly the same as the previous one. This is how you iterate through the array and take an action on each element. You also don’t need to know how many elements are in the array when you write the for loop; you stop the loop when i reaches myIntArray.Length.

Example 10-1 shows the whole program, brief as it is.

Example 10-1. for loops are the most common way to work with arrays

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Example_10_1_ _ _ _Using_arrays
{
    class Tester
    {
        public void Run( )
        {
            int[] myIntArray = new int[10];

            //populate the array
            for (int i = 0; i < myIntArray.Length; i++)
            {
                myIntArray[i] = 2 * (i + 1);
            }

            //output the array
            for (int i = 0; i < myIntArray.Length; i++)
            {
                Console.WriteLine("Value in index {0} is {1}.", 
                                  i, myIntArray[i]);
            }

        }
        static void Main(string[] args)
        {
            Tester t = new Tester( );
            t.Run( );
        }
    }
}

The output should look like this:

Value in index 0 is 2.
Value in index 1 is 4.
Value in index 2 is 6.
Value in index 3 is 8.
Value in index 4 is 10.
Value in index 5 is 12.
Value in index 6 is 14.
Value in index 7 is 16.
Value in index 8 is 18.
Value in index 9 is 20.

Go ahead and change the < in the first loop to <=, and run the program again. You’ll get yourself a nice crash. That’s because when the loop runs the final time (when i equals 10), the body of the loop tries to assign a value to myIntArray[10], which doesn’t exist. You’re trying to write into an area of memory that’s not there, and the compiler doesn’t like that.

You can use arrays with user-defined classes as well, of course, but you have to do a bit of extra work because the objects won’t be initialized automatically. Example 10-2 shows a simple Employee class being used with an array. Notice that the class includes an automatic property for the Employee ID, as introduced in Chapter 8.

Example 10-2. You can use objects with arrays almost as easily as primitive types

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Example_10_2_ _ _ _Arrays_and_Objects
{
    // a simple class to store in the array
    public class Employee
    {
        public int EmpID { get; set; }

        public Employee(int empID)
        {
            EmpID = empID;
        }
    }
    public class Tester
    {
        static void Main( )
        {
            Employee[] empArray;
            empArray = new Employee[3];

            // populate the arrays
            for (int i = 0; i < empArray.Length; i++)
            {
                empArray[i] = new Employee(i + 1005);
            }

            // output array values
            Console.WriteLine("
employee IDs:");
            for (int i = 0; i < empArray.Length; i++)
            {
                Console.WriteLine(empArray[i].EmpID);
            }
        }
    }
}

The output looks like this:

employee IDs:
1005
1006
1007

In this example, the Employee IDs start at 1005 and proceed from there. You see that you need to create each Employee object with the new keyword in the for loop. To access the EmpID member of each Employee object, you use the dot notation: empArray[i].EmpID. Notice that the dot comes after the square brackets. Remember that empArray represents the entire array, but empArray[i] represents a single Employee, so you can access the member fields and methods of each individual object.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset