ASP.NET Basics (part 5): Cooking Up A Storm

Learn all about arrays and enumerations, and use them for more complex data storage and manipulation.

Deeper Waters

The last article in this series marked the end of the basic section of this ASP.NET tutorial. Over the last four articles, I've attempted to give you a gentle introduction to C# and ASP.NET. I've shown you the basic components of an ASP.NET program; explained how to define simple variables; illustrated how to control the flow of your program through "if" and "switch" conditional expressions; and demonstrated how to run a particular set of statements repeatedly with "while" and "for" loops.

Now that you know the basic control structures available in C# - variables, conditionals and loops - it's time to move into murkier territory. In addition to the simple variables discussed previously, C# also comes with a whole set of more complex variables that build on the simple variables you've encountered earlier to allow more complex data storage and manipulation. Over the course of this article, I'm going to give you a crash course in one of the more interesting and useful ones, arrays, and show you how you can use them to make your code jump through ever more interesting loops. Onwards and upwards, then!

What's For Dessert?

Thus far, the variables you've used contain only a single value - for example,

<%
int i = 0
%>

However, array variables are a different kettle of fish altogether. An array is a complex variable that allows you to store multiple values in a single variable; it comes in handy when you need to store and represent related information. An array variable can, thus, best be thought of as a "container" variable, which can contain one or more values. For example,

<%
string [] desserts = {"chocolate mousse", "tiramisu", "apple pie", "chocolate fudge cake", "caramel custard"};
%>

Here, "desserts" is an array variable, which contains the values "chocolate mousse", "tiramisu", "apple pie", "chocolate fudge cake", and "caramel custard". It is thus clear that array variables are particularly useful for grouping related values together - names, dates, phone numbers of ex-girlfriends et al.

The definition shown above is a shorthand method to define an array. The proper syntax to define an array in C# is shown below.

<%
// define the type of array
string [] desserts;

// initialize array
// the number indicates the number of elements the array will hold
desserts = new string[5];

// assign values to each element
// of the "desserts" array defined above
desserts[0] = "chocolate mousse";
desserts[1] = "tiramisu";
desserts[2] = "apple pie";
desserts[3] = "chocolate fudge cake";
desserts[4] = "caramel custard";
%>

Defining an array variable in C# is a multi-step process, as compared to languages like PHP and Perl; you need to first declare the variable and its type, and then actually create the array.

The various elements of the array are accessed via an index number, with the first element starting at zero. So, to access the element

chocolate mousse

you would use the notation

desserts[0]

while

"chocolate fudge cake"

would be

desserts[3]
  • essentially, the array variable name followed by the index number enclosed within square braces. Notice that the first element of the array is referred to by index number 0 instead of 1; geeks refer to this as "zero-based indexing".

Unlike less strict programming languages like PHP and Perl, C# arrays can only store data of the type specified at the time of declaring the array variable - a string array cannot hold numbers, or vice-versa. So, if you were to try the following,

<%
string [] desserts = new string[5];

// assign an integer value
desserts[0] = 100;
%>

C# would fail with an ugly type conversion error message.

Changing Things Around

In order to modify an element of an array, you need to simply assign a new value to the corresponding variable. If you wanted to replace "chocolate fudge cake" with "chocolate chip cookies", you'd simply use

<%
desserts[3] = "chocolate chip cookies";
%>

and the array would now read

<%
string [] desserts = {"chocolate mousse", "tiramisu", "apple pie", "chocolate chip cookies", "caramel custard"};
%>

You can obtain the number of items in an array with the "Length" property (note the uppercase L), as demonstrated below:

<script language="C#" runat="server">
void Page_Load()
{
    string [] desserts = {"chocolate mousse", "tiramisu", "apple pie", "chocolate fudge cake", "caramel custard"};
    output.Text = "The dessert menu contains " + desserts.Length + " items.";
}
</script>
<html>
<head><title>Dessert Menu</title></head>
<body>
<asp:label id="output" runat="server" />
</body>
</html>

And the output is:

You can use a "for" loop to iterate through the elements of an array, as the following example demonstrates.

<script language="C#" runat="server">
void Page_Load()
{
    // define counter
    int counter;

    string [] desserts = {"chocolate mousse", "tiramisu", "apple pie", "chocolate fudge cake", "caramel custard"};

    for (counter = 0; counter < desserts.Length; counter++)
    {
        output.Text = output.Text + "<li>" + desserts[counter] + "<br>";
    }
}
</script>
<html>
<head><title>Dessert Menu</title></head>
<body>
Desserts available:
<ul>
<asp:label id="output" runat="server" />
</ul>
</body>
</html>

And the output is as follows:

A Full Meal

As explained on the previous page, an array makes it possible to store a group of logically-related values - in this case, a list of mouth-watering desserts. However, there's more to a meal than just the desserts; the desserts are usually preceded by the starters and the main courses (more than one if the cook is a culinary enthusiast).

Now, if I wanted to, I could create an array to store the entire set of items for a meal, as below:

<%
string [] meals = {"vegetable soup", "cream of mushroom soup", "chicken soup", "lasagna", "pasta", "tandoori chicken", "chocolate mousse", "tiramisu", "apple pie" };
%>

The only problem here? There's no way to distinguish between starters, main courses and desserts. What is really needed is a variable that stores all the values, yet provides some way to distinguish between them, as below:

Starter vegetable soup, cream of mushroom soup, chicken soup

Main course lasagna, pasta, tandoori chicken

Dessert chocolate mousse, tiramisu, apple pie

Is there a way to do this in C#? Sure, with a multi-dimensional array.

Thus far, the arrays that you've seen have been one-dimensional arrays; they store values in a single column. However, C# also permits two-dimensional arrays, which allow you to store data in rows and columns. Here's an example:

<%

// define the type of array
string [,] meals;

// initialize array with two dimensions
meals = new string[3,4];

// assign values to each element
meals[0,0] = "vegetable soup";
meals[0,1] = "cream of mushroom soup";
meals[0,2] = "chicken soup";
meals[1,0] = "lasagna";
meals[1,1] = "pasta";
meals[1,2] = "tandoori chicken";
meals[2,0] = "chocolate mousse";
meals[2,1] = "tiramisu";
meals[2,2] = "apple pie";

%>

Here the index is made up two values - the first represents the row and the second represents the column. If you look closely, you'll see that the first row stores the starters, the second stores the main course dishes and the last contains the desserts.

So, to access the element

chocolate mousse

you would use the notation:

meals[2,0]

Note the use of two values in the index to access the element: the first value represents the "row" and the second represents the "column".

Let's now put together a simple script to output the menu in a tabular format:

<script language="C#" runat="server">
void Page_Load()
{
    // store the names of the courses
    string [] courses = {"Starters"," Main Course Dishes", "Desserts"};

    // variables to store the number of rows and columns
    int rows = 3, columns = 3;

    // define the type of array
    string [,] meals;

    // initialize array with two dimensions
    meals = new string[rows,columns];

    // assign values to each element

    // Starters in row #1
    meals[0,0] = "vegetable soup";
    meals[0,1] = "cream of mushroom soup";
    meals[0,2] = "chicken soup";

    // Main Course Dishes in row #2
    meals[1,0] = "lasagna";
    meals[1,1] = "pasta";
    meals[1,2] = "tandoori chicken";

// Desserts in row #3
    meals[2,0] = "chocolate mousse";
    meals[2,1] = "tiramisu";
    meals[2,2] = "apple pie";

    // the outer "for" loop to access each row
    for(int i = 0; i < rows; i++)
    {

        output.Text = output.Text + "<tr>";
        output.Text = output.Text + "<td><b>" + courses[i] + "</b></td>";

        // the inner "for" loop to access each column
        for(int j = 0; j < columns; j++)
                {
        output.Text = output.Text + "<td>" + meals[i,j] + "</td>";
        }

        output.Text = output.Text + "</tr>";
    }

}
</script>
<html>
<head><title>Full Course Meal</title></head>
<body>
<table width="75%" border="1" cellspacing="0" cellpadding="5" border="1">
<asp:label id="output" runat="server" />
</table>
</body>
</html>

And here's the output.

As usual, I start the script by defining some variables - two integers to store the number of rows and columns for the two-dimensional array, followed by the arrays themselves. The first array, "courses", stores the names of the three courses, while the second, "meals", actually stores the values for each.

Next, I have the most crucial part of the code: the two "for" loops used to iterate through the "meals" array. This deserves closer attention.

<%
    // snip

    // the outer "for" loop to access each row
    for(int i = 0; i < rows; i++)
    {

        output.Text = output.Text + "<tr>";
        output.Text = output.Text + "<td><b>" + courses[i] + "</b></td>";

        // the inner "for" loop to access each column
        for(int j = 0; j < columns; j++)
        {

            output.Text = output.Text + "<td>" + meals[i,j] + "</td>";
        }
        output.Text = output.Text + "</tr>";
    }

    // snip
%>

As you can see, the first "for" loop iterates through the rows of the array, with the variable "i" keeping track of the first dimension. Within this outer loop is another "for" loop, used to access each column of the array using the variable "j". Combined, these two loops make it possible to access each and every element of the two-dimensional array, by iterating across the length and breadth of the array.

Getting Lucky

So far, I have used the "for" loop to navigate through the contents of an array. But there's more than one way to skin a cat...and so, C# also lets you iterate over an array with a new loop construct, one I conveniently avoided explaining last time. It's called a "foreach" loop, and it looks like this:

foreach (element in array)
{
    do this!
}

Here is a simple example for the "foreach" loop.

<script language="c#" runat="server">
void Page_Load()
{

    // define the type of array
    int [] lucky_numbers;

    // initialize array
    lucky_numbers = new int[5];

    // assign values to each element
    lucky_numbers[0] = 3;
    lucky_numbers[1] = 6;
    lucky_numbers[2] = 9;
    lucky_numbers[3] = 21;
    lucky_numbers[4] = 27;

    // use the foreach loop
    // to iterate over each element
    foreach(int lucky_number in lucky_numbers)
       {
        output.Text = output.Text + "&nbsp;&nbsp;<b>" + lucky_number + "</b>";
    }

}
</script>
<html>
<head><title>Getting Lucky</title></head>
<body>
Here are my lucky numbers: <asp:label id="output" runat="server" />.
What are yours?
</body>
</html>

This is what you should see in our browser.

Here, I've first defined an array of integers called "lucky_numbers", to store a set of numbers. Next, I've used the "foreach" loop to iterate over the loop and print each element of the array.

<%
// snip

// use the foreach loop
// to iterate over each element
foreach(int lucky_number in lucky_numbers)
{
    output.Text = output.Text + "&nbsp;&nbsp;<b>" + lucky_number + "</b>";
}

// snip
%>

Each time the loop runs, it stores the current element of the array in the "lucky_number" instance variable. Once the loop runs out of its elements to process, it automatically exits and control passes to the line following it.

How about iterating over a two-dimensional array? Take a look:

<script language="c#" runat="server">
void Page_Load()
{

    // define an array
    string [,] meals;

    // initialize array with two dimensions
    meals = new string[3,3];

    // assign values to each element
    meals[0,0] = "vegetable soup";
    meals[0,1] = "cream of mushroom soup";
    meals[0,2] = "chicken soup";
    meals[1,0] = "lasagna";
    meals[1,1] = "pasta";
    meals[1,2] = "tandoori chicken";
    meals[2,0] = "chocolate mousse";
    meals[2,1] = "tiramisu";
    meals[2,2] = "apple pie";

    foreach(string dish in meals)
       {
        output.Text = output.Text + "&nbsp;&nbsp;" + dish;
    }

}
</script>
<html>
<head><title>Full Course Meal</title></head>
<body>
<asp:label id="output" runat="server" />.
</body>
</html>

This is the output.

As you can see, the "foreach" loop does not give me as much control over the array, as compared to the two "for" loops demonstrated in the earlier example.

Thus far, the number of columns in the array was equal to the number of rows. However, this is not a hard and fast rule - it is possible to define a multi-dimensional array which is not so symmetrical in its dimensions, such as

books[10,4];

or

authors[30,5]

However, using an array with three or more dimensions leads to complex programming logic, and code that is difficult to write, read and debug; it should therefore be avoided as far as possible.

Jagged Little Pill

In all the examples on the previous pages, the arrays have been symmetrical, in that every row of the array has had an equal number of elements. For example, an array defined as

meals[3,3]

will always hold 9 values, with each row holding an equal number of columns (3). Of course, it is possible that some of these 9 elements might not be assigned any value; in this case, they will hold the default value defined by C# for the data type of that array.

C# also allows you to define an array that does not have the same number of columns across its rows. It's called a "jagged array", and here's an example:

<%

string [][] meals= new string [3][];
meals [0] = new string[1];
meals [1] = new string[3];
meals [2] = new string[2];

meals[0][0] = "cream of mushroom soup";

meals[1][0] = "pasta";
meals[1][1] = "lasagne";
meals[1][2] = "tandoori chicken";

meals[2][0] = "chocolate mousse";
meals[2][1] = "tiramisu";

%>

Since a jagged array itself contains other arrays, it is not surprisingly often referred to as an "array of arrays".

How about an example? Here's a script that defines a jagged array, assigns values to its elements and displays the values using a "for" loop:

<script language="c#" runat="server">
void Page_Load()
{

    // store the names of the courses
    string [] courses = {"Starters"," Main Course Dishes", "Desserts"};

    // define the array
    string [][] meals= new string [3][];
    meals [0] = new string[1];
    meals [1] = new string[3];
    meals [2] = new string[2];

    // assign values to the elements

    // for the first row, starters
    // one column
    meals[0][0] = "cream of mushroom soup";

    // for the second row, main courses
    // three columns
    meals[1][0] = "pasta";
    meals[1][1] = "lasagne";
    meals[1][2] = "tandoori chicken";

    // for the third row, desserts
    // two columns
    meals[2][0] = "chocolate mousse";
    meals[2][1] = "tiramisu";

    // a "for" loop to iterate through the array
    for(int i = 0; i < meals.Length; i++)
       {
        output.Text = output.Text + "<tr>";
        output.Text = output.Text + "<td><b>" + courses[i] + "</b></td>";
        for(int j = 0; j < meals[i].Length; j++)
        {
            output.Text = output.Text + "<td>" + meals[i][j] + "</td>";
        }
        output.Text = output.Text + "</tr>";
    }

}
</script>
<html>
<head><title>Full Course Meal</title></head>
<body>
<body>
<table width="75%" cellspacing="0" cellpadding="5" border="0">
<asp:label id="output" runat="server" />
</table>
</body>
</html>

Here's the output.

The script starts with the definition of the jagged array.

<%

    // define the array
    string [][] meals= new string [3][];
    meals [0] = new string[1];
    meals [1] = new string[3];
    meals [2] = new string[2];

    // assign values to the elements

    // for the first row, starters
    // one column
    meals[0][0] = "cream of mushroom soup";

    // for the second row, main courses
    // three columns
    meals[1][0] = "pasta";
    meals[1][1] = "lasagne";
    meals[1][2] = "tandoori chicken";

    // for the third row, desserts
    // two columns
    meals[2][0] = "chocolate mousse";
    meals[2][1] = "tiramisu";

    // snip

%>

Note the manner in which I have assigned values to the various elements. A comparison with previous examples will illustrate the difference between this syntax, and that used for "regular" multi-dimensional arrays.

<%

// snip

    // the "for" loop to iterate through the array
    for(int i = 0; i < meals.Length; i++)
    {
        output.Text = output.Text + "<tr>";
        output.Text = output.Text + "<td><b>" + courses[i] + "</b></td>";
        for(int j = 0; j < meals[i].Length; j++)
        {
            output.Text = output.Text + "<td>" + meals[i][j] + "</td>";
        }
        output.Text = output.Text + "</tr>";
    }

// snip
%>

Once again, I have used two "for" loops to iterate over the array. Note my usage of the "Length" property to find the number of elements at each level; this ensures that the script does not attempt to access an element that does not exist.

Setting Limits

Another interesting type of complex variable in C# is the so-called enumeration, or "enum", type, which allows you to restrict the value of a variable to a list of pre-defined values. Here's what it looks like:

enum variable-name {list of values}

And here's an example:

<%
enum Months { January, February, March, April, May, June, July, August, September, October, November, December };
%>

In order to use the enumeration, you need to define a variable of that type and assign it a value, as below.

<%
Months myBirthMonth = Months.July;
%>

Try as you might, C# will not allow you to assign a other value other than those listed in the enumeration to the variable "myBirthMonth".

The next example demonstrates the use of the "Months" enumeration in a simple C# script.

<script language="c#" runat="server">

enum Summer { April = 4, May = 5, June = 6, July = 7};

void Page_Load()
{

    DateTime date = System.DateTime.Now;

    Summer current_month;

    current_month = (Summer) date.Month;

    if (Enum.IsDefined(typeof(Summer), current_month))
    {
        output.Text = "Summer time! Get to work on that tan!";
    }
    else
    {
        output.Text = "It ain't summer, bud, so no point stocking up on suntan lotion";
    }

}
</script>
<html>
<head><title>Summer Time</title></head>
<body>
<asp:label id="output" runat="server" />
</body>
</html>

Here is what the output looks like if it's summer,

and here's what it looks like when it's not.

In this example, I've used a "Summer" enumeration to create a set of values representing the four summer months of the year.

Typically, each value in an "enum" is associated with an integer. By default, the compiler will automatically assign an integer value, starting with 0 for the first value. But this does not really suit my purposes on two counts: first, there is no such thing as a 0th month and second, I need the month to be assigned a number corresponding to its correct position in the calendar. Therefore, I have explicitly defined integer values for each month.

<%
enum Summer { April = 4, May = 5, June = 6, July = 7};
%>

Next, the current month (an integer value, by default) is obtained from the system, and cast into the "Summer" enum data type.

<%
DateTime date = System.DateTime.Now;
Summer current_month;
current_month = (Summer) date.Month;
%>

Finally, the IsDefined() method of the "Enum" object is used to check if the value assigned to the "current_month" variable exists in the definition for the "Summer" enumeration. Don't worry too much about this, I'll be discussing objects and methods a little later on in this series. For the moment, all you need to know is that the IsDefined() method returns true if the value exists in the enumeration, and false if it does not; the output will change accordingly.

Over And Out

And that's about it for today. I started this article with an introduction to arrays, a complex variable type that allows developers to store multiple values in a single variable. This was followed by a quick rundown on how to initialize and manipulate them. As part of your introduction to arrays, I also showed you how to define, access and use multi-dimensional and jagged arrays, and iterate over them with the special "foreach" loop. Finally, I wrapped things up with a brief look at enumerations, which make it possible to restrict variable values to a predefined set.

In the next segment of this article, I will explain the concept of functions - a block of statements that can be grouped together as a named entity.Functions make it possible to group your code into logical, reusable blocks, and can save you a fair amount of repetitive typing - as well as offering a more efficient way of structuring your C# programs. Make sure you come back for that!

Note: Examples are illustrative only, and are not meant for a production environment. Melonfire provides no warranties or support for the source code described in this article. YMMV!

This article was first published on12 Sep 2003.