Arrays are one of the most fundamental data structures in C# programming, allowing you to store multiple values of the same type in a single variable. Whether you’re developing a simple console application or a complex enterprise system, understanding arrays is essential. This guide will walk you through everything you need to know about arrays in C#, from basic concepts to practical usage patterns.
What Are Arrays in C#?
An array in C# is a fixed-size, zero-indexed collection of elements of the same data type. Being zero-indexed means the first element is accessed with index 0, the second with index 1, and so on. Arrays are reference types that inherit from the System.Array
class, which provides various methods and properties to work with arrays efficiently.
Single-Dimensional Arrays
Declaration and Initialization
There are several ways to declare and initialize single-dimensional arrays in C#:
// Declaration without initialization int[] numbers; // Declaration with size allocation int[] scores = new int[5]; // Creates an array with 5 elements, all set to default (0) // Declaration with initialization int[] ages = new int[] { 25, 30, 35, 40, 45 }; // Shorthand initialization int[] values = { 1, 2, 3, 4, 5 }; // Declaration using var keyword var prices = new double[] { 19.99, 29.99, 39.99 };
Accessing Array Elements
You can access array elements using their index:
int[] numbers = { 10, 20, 30, 40, 50 }; int firstNumber = numbers[0]; // 10 int thirdNumber = numbers[2]; // 30 // Modifying an element numbers[1] = 25; // Changes the second element from 20 to 25
Common Properties and Methods
Arrays in C# come with several useful properties and methods:
int[] data = { 3, 7, 2, 9, 5 }; // Properties int length = data.Length; // 5 int rank = data.Rank; // 1 (number of dimensions) // Methods Array.Sort(data); // Sorts the array: { 2, 3, 5, 7, 9 } int position = Array.IndexOf(data, 5); // Returns 2 (index of value 5) Array.Reverse(data); // Reverses the array: { 9, 7, 5, 3, 2 } Array.Clear(data, 0, 2); // Clears first two elements: { 0, 0, 5, 3, 2 }
Multi-Dimensional Arrays
C# supports two types of multi-dimensional arrays: rectangular and jagged.
Rectangular Arrays
Rectangular arrays have a fixed number of rows and columns:
// Declaration with size allocation int[,] matrix = new int[3, 4]; // 3 rows, 4 columns // Declaration with initialization int[,] grid = new int[,] { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 } }; // Accessing elements int value = grid[1, 2]; // Returns 7 (row 1, column 2) // Getting dimensions int rows = grid.GetLength(0); // 3 int columns = grid.GetLength(1); // 4
Jagged Arrays (Arrays of Arrays)
Jagged arrays are arrays of arrays, where each sub-array can have different lengths:
// Declaration int[][] jaggedArray = new int[3][]; // Initialization jaggedArray[0] = new int[] { 1, 2, 3 }; jaggedArray[1] = new int[] { 4, 5 }; jaggedArray[2] = new int[] { 6, 7, 8, 9 }; // Alternative declaration and initialization int[][] numbers = new int[][] { new int[] { 1, 2, 3 }, new int[] { 4, 5 }, new int[] { 6, 7, 8, 9 } }; // Accessing elements int value = jaggedArray[2][1]; // Returns 7
Common Array Operations
Iterating Through Arrays
You can iterate through arrays using various loop constructs:
int[] numbers = { 10, 20, 30, 40, 50 }; // Using for loop for (int i = 0; i < numbers.Length; i++) { Console.WriteLine(numbers[i]); } // Using foreach loop foreach (int number in numbers) { Console.WriteLine(number); } // Iterating through a 2D array int[,] matrix = { { 1, 2, 3 }, { 4, 5, 6 } }; for (int i = 0; i < matrix.GetLength(0); i++) { for (int j = 0; j < matrix.GetLength(1); j++) { Console.WriteLine(matrix[i, j]); } }
Array Manipulation
C# provides several methods for manipulating arrays:
int[] source = { 1, 2, 3, 4, 5 }; // Creating a copy int[] destination = new int[source.Length]; Array.Copy(source, destination, source.Length); // Clone int[] clone = (int[])source.Clone(); // Resizing Array.Resize(ref source, 10); // Resizes to 10 elements, padding with zeros // Finding elements bool exists = Array.Exists(source, element => element > 3); int found = Array.Find(source, element => element % 2 == 0); int[] filtered = Array.FindAll(source, element => element % 2 == 0);
Performance Considerations
When working with arrays in C#, keep these performance considerations in mind:
- Fixed Size: Arrays have a fixed size after creation. If you need a dynamically sized collection, consider using
List<T>
. - Memory Allocation: Arrays allocate contiguous memory blocks, making element access very fast (O(1) time complexity).
- Value vs. Reference Types: Arrays of value types store the actual values, while arrays of reference types store references to objects.
- Bounds Checking: C# performs bounds checking at runtime to prevent access beyond array boundaries. This adds a slight overhead but improves safety.
int[] numbers = { 1, 2, 3 }; // This will throw an IndexOutOfRangeException // int value = numbers[5];
Advanced Topics
Array Covariance
C# supports array covariance, which means an array of a more derived type can be assigned to an array of a less derived type:
class Animal { } class Dog : Animal { } Dog[] dogs = new Dog[3]; Animal[] animals = dogs; // This is valid due to covariance
However, this can lead to runtime exceptions if misused:
animals[0] = new Animal(); // This will throw ArrayTypeMismatchException at runtime
Span<T> for Modern Array Manipulation
C# 7.2 introduced Span<T>
, a ref-like structure that provides a type-safe, memory-efficient way to work with contiguous regions of memory:
int[] numbers = { 1, 2, 3, 4, 5 }; // Create a span over the entire array Span<int> wholeSpan = numbers; // Create a span over a portion of the array Span<int> partialSpan = numbers.AsSpan(1, 3); // Elements at index 1, 2, 3 // Modify through the span partialSpan[0] = 22; // Changes numbers[1]
Practical Examples
Searching in Arrays
int[] data = { 7, 3, 9, 2, 5, 11, 4 }; int searchValue = 5; // Linear search int linearIndex = -1; for (int i = 0; i < data.Length; i++) { if (data[i] == searchValue) { linearIndex = i; break; } } // Using built-in method int builtInIndex = Array.IndexOf(data, searchValue);
Sorting Examples
string[] names = { "Charlie", "Alice", "David", "Bob" }; // Sort alphabetically Array.Sort(names); // Result: { "Alice", "Bob", "Charlie", "David" } // Custom sorting using a comparison delegate Array.Sort(names, (x, y) => x.Length.CompareTo(y.Length)); // Result (sorted by length): { "Bob", "Alice", "David", "Charlie" }
Conclusion
Arrays are a powerful and efficient way to work with collections of data in C#. From simple single-dimensional arrays to complex multi-dimensional structures, they provide the foundation for many algorithms and data processing tasks. By understanding how to declare, initialize, and manipulate arrays effectively, you’ll have a solid foundation for more advanced C# programming concepts.
Remember that while arrays are ideal for fixed-size collections with fast access requirements, other collection types like List<T>
, Dictionary<TKey, TValue>
, and HashSet<T>
might be more appropriate depending on your specific needs. Always consider the requirements of your application when choosing the right data structure.