So you’ve started your journey into C# development. Learning any new language or framework can be a challenging road. However, you need not despair. Allow those who have gone before you to lead the way and guide you on your journey. Today’s leg of the journey is the C# array.
In this post, we’ll discuss what an array is. We’ll see how to use one in our code, and we’ll discuss how best to use it and what pitfalls can hurt your code quality.
C# Array: Under the Hood
If you want to use arrays in C#, you have to understand what they are and how they work. So, what is an array?
The simple definition is that an array is an indexed list. This means that an array holds a collection of elements in an ordered list. Every element of the array must be the same type.
In other words, you can have an array of integers or an array of strings, but not an array that holds both integers and strings.
When you initialize a C# array, the .NET runtime reserves a block of memory sufficient to hold the elements. It then stores the elements of the array sequentially within that block of memory.
Declaring an Array in C#
To understand how array declaration works in C#, you must keep in mind the role the square brackets play in the syntax. Consider the following lines of code:
string s; int n; DateTime today;
In the examples above, we declare three variables, whose types are string, int, and DateTime, respectively. Now consider yet another example:
string[] names; int[] numbers; DateTime[] dates;
In the lines of code above, we’ve again declared three variables. But this time, their types are string[], int[], and DateTime[], respectively. See? “DateTime” is a type, and “DateTime[]” is another type (we read that as “array of DateTime”, “array of integers”, etc).
I’ve seen many junior developers struggling to understand the role of the square brackets. To their credit, it is somewhat confusing.
Just keep in mind that when declaring arrays the square brackets are part of the type’s name and you’ll be fine.
Initializing a C# Array
In the previous section, we covered how to declare variables that can hold arrays.
But we haven’t initialized the variables themselves, so we’re going to do that now.? The following code both declares and initializes a variable with an array of integers that holds five elements:
int[] myArray = new int[5];
You can also use type inference in the left-hand side of the declaration, making the following line equivalent to the one above:
var myArray = new int[5];
The blue block above represents the memory that is available to your computer. When the code above executes, the runtime reserves the memory and places your elements in order within that reserved memory.
The square brackets after each element of?myArray hold the index of that element. Indices start at zero, so an array of five elements has the indices of 0, 1, 2, 3, and 4. You access a specific element of the array by using the index like so:
// grab the 3rd item of the array and save it to another variable var someElement = myArray[2]
At this point, however, you haven’t actually placed any values in the array yet. Let’s do that next.
Assigning Values to an Array in C#
There are two ways to place values in a C# array. You can either access each element of the array and set the value or you can use the collection initializer syntax that C# provides. Let’s take a look at both.
// Accessing each individual element int[] myArray = new int[5]; myArray[0] = 1; myArray[1] = 4; myArray[2] = 9; myArray[3] = 16; myArray[4] = 25; // Using the collection initializer int[] myArray = new int[5] {1, 4, 9, 16, 25}; // Another way to use the collection initializer int[] myArray = {1, 4, 9, 16, 25};
Which do you think is better? I’ll give you a hint: it’s all about readability. The C# compiler turns the second and third example into the first example so they’re actually equivalent from a pure code standpoint.
Best Practice #1: Use collection intializers to create arrays. It’s more readable and, frankly, easier to type.
Pitfall #1: Manually populating an array can lead to hard-to-find bugs and runtime errors due to mistyped indices. If you try to access an element that doesn’t exist, your application will throw an exception at runtime.
Using C# Arrays
C# arrays have some key characteristics that make them incredibly useful and efficient. In fact, when you dig deeper into more advanced collection classes such as Lists, you’ll find that they’re really wrappers around arrays.
The versatility and efficiency of arrays come?from two major factors. First, they’re implemented in the runtime itself. That’s why they get special syntax that no other type has.
For instance, a List class is a C# class that was written by Microsoft to expose certain functionality. You have to create a new List object before you use it.
Arrays are implemented in the guts of the runtime, using languages closer to the metal. So you simply add square brackets to the type to create an array, which is unique among types. Arrays are a key building block of the language.
The second factor in their performance advantages is how they are stored in memory and accessed.
C# arrays are stored by reserving a block of memory that equals the amount needed to hold the elements.
If you store five integers that each take up four bytes of memory, the runtime allocates 20 bytes of memory (4 x 5) to hold the values. It then puts the values into the array in order, right next to each other.
So if we take our example from before, we initialize an array with the first five squares.
int[] myArray = {1, 4, 9, 16, 25};
It will look like this in memory:
The beauty of this data structure is that the values are right next to each other. When you want to access an element of an array, you simply start at the beginning and jump the number of bytes necessary to get to the next element.
The following diagram illustrates the concept. Once you have the memory location of the first element, the rest is simply an addition problem. This is why arrays are so fast when retrieving data.
This efficiency comes at a price, however.
Once you create an array, you can’t add more elements to it. It’s a fixed size. There’s no guarantee that the memory that follows the array is available for use. Therefore, you shouldn’t use arrays for lists of things that can change over the use of the application.
Best Practice #2: Use arrays when you have a list of things that don’t change. A good example is an array that holds the days of the week.
Pitfall #2: If you need to add things dynamically to a collection, using an array will not work for you (at least not without a lot of extra code). Use another collection type.
The way arrays work also means that you have to be mindful of how much space you allocate to your array. Be mindful of only using the space you need.
Best Practice #3: For large lists of data, only create the size of the array you need. Use what you ask to reserve.
Pitfall #3😕 If you create a large array but don’t use it all, that memory will be unavailable for your or other applications to use.
C# Array: When You Need to Grab the Elements
When you want to do something to all of the elements of an array, you need to access all of the elements in turn and process them. This is called?iterating over an array. There are two ways to iterate over an array in C#, the for loop and the foreach statement.
On the surface, these two look very similar. However, there are important differences that you should understand. Let’s take a look at both in code and discuss the differences.
int[] myArray = {1, 4, 9, 16, 25 }; for (int i = 0; i < myArray.Length; i++) { Console.WriteLine(myArray[i]); } foreach (var number in myArray) { Console.WriteLine(number); }
The?for?loop functions by directly accessing each element of an array using the square brackets and doing something with it. The?foreach loop assigns a variable to the value of each element in turn, and then you can read that element.
There is an important distinction here: the foreach loop is read-only. You can’t change the value of the elements as they go through the loop.
Also,?foreach iterates through the entire array no matter what. If you want to only iterate over a portion of the array, you must use a?for?loop.
Best Practice #4: Use the?for?loop if you need to iterate over a portion of an array or you need to change the elements of the array in some fashion as you iterate. Use?foreach when you don’t want to change anything in the array and you need to iterate through all elements.
Pitfall #4: Understand the differences between the?for?and?foreach loops. It’s more than just syntax. When using the?for loop, be very careful with the indices so you don’t run into runtime exceptions from iterating too far and accessing an element that doesn’t exist.
Taking the C# Array a Step Further: Multidimensional Arrays
Up until now, we’ve covered arrays that are single-dimensional. But arrays in C# can have more than one dimension. What does that mean in practice?
Single-dimensional arrays are useful to represent data expressed in such a way that each value is associated with a single index.
For instance, let’s say you need to store the average temperature of the last 30 days. You could create an array of double with 30 items and be done with it.
You’d just have to be careful and not forget that arrays’ indexes are zero-based?so to access the first value you’d have to use the index 0, and so on.
But what if you needed to store the average daily temperature for a whole year?
Sure, you could use an array of 365 (or 366) items, but that would make it slightly harder to retrieve the result for a specific day. A better approach would be perhaps to employ a multidimensional array.
Multidimensional Arrays Example
Take a look at the following example:
double[,] temperatures = new double[12, 31];
The line above creates a multidimensional array, whose dimensions are 12 and 31. Visually, it helps to think of this as a table (or matrix) with 12 rows and 31 columns.
To assign a value to our multidimensional array, we need to use both indexes.
In the following example, we assign the average temperature for January 15th:
temperatures[0, 14] = 15;
You can also declare the array omitting its rank, which will then be inferred by the right-hand side of the declaration:
int[,] multi = { { 1, 1 }, { 2, 3 }, { 5, 8 }, { 13, 21 } };
Keep in mind that, even though we’re using two-dimensional arrays for our examples, you’re not restricted to this number of dimensions. You can easily use arrays with three, four, or more dimensions.
Finally, how do we loop through a multidimensional array?
The same way we loop through a single-dimensional one: by using a for or foreach. The only difference is that, in the case of multidimensional arrays, you’d need n nested for/foreach structures, where n is the number of dimensions of the array.
The C# Array as an IEnumerable
Here is another important trait of arrays in C#: they all implement the IEnumerable and IEnumerable<T> interfaces. In other words, if you have an int[], then you also have an IEnumerable<int>.
So, how is this useful?
- You can loop through an array’s items using the foreach loop.
- You can use the LINQ extension methods (such as Select, Where and Aggregate) on arrays.
Take a look at the example below, noticing that we had to include the “System.Linq”:
using System; using System.Linq; class MainClass { public static void Main (string[] args) { int[] numbers = { 1, 2, 3, 4, 5 }; var squares = numbers.Select(x => x * x); var greaterThanFour = squares.Where(x => x > 4); var sum = greaterThanFour.Sum(); Console.WriteLine ("Result: {0}", sum); } }
What’s Next?
Arrays are one of the basic data structures in the C# language. Even so, they’re really fascinating when you dig into what makes them special and super useful in your applications. Use arrays effectively, and you’ll be able to build anything.
Take some time to practice with arrays and use them in your everyday coding where they make sense. Having a deep understanding of how arrays work will help you throughout your journey as a software engineer.
You might also be interested in further reading about other C# language concepts:
Learn more how CodeIt.Right can help you automate code reviews and improve the quality of your code.
2 Comments. Leave new
Awesome. Thank you
[…] Note: This post originally appeared on SubMain’s blog. They give you tools that help you write better C# […]