Arrays and Collections in .NET
This document provides an in-depth overview of arrays and collections in the .NET framework. Understanding how to store and manage data efficiently is crucial for building robust and performant applications.
Arrays
Arrays are fixed-size data structures that store elements of the same type. They are zero-indexed, meaning the first element is at index 0.
Declaring and Initializing Arrays
// Declaring an array of integers
int[] numbers;
// Declaring and initializing an array with values
string[] names = {"Alice", "Bob", "Charlie"};
// Declaring and initializing an array with a specific size
char[] letters = new char[5];
Accessing Array Elements
string firstName = names[0]; // "Alice"
letters[2] = 'X';
Array Properties and Methods
The System.Array
class provides useful properties and methods:
Length
: Gets the total number of elements in the array.Rank
: Gets the number of dimensions (rank) of the array.Sort()
: Sorts the elements in ascending order.Reverse()
: Reverses the order of elements.
int count = names.Length; // 3
Array.Sort(names);
Array.Reverse(letters);
Collections
Collections are more flexible than arrays and provide various ways to store and manipulate groups of objects. They are part of the System.Collections
and System.Collections.Generic
namespaces.
Common Non-Generic Collections (System.Collections
)
These collections store objects of type object
, requiring casting and potentially leading to runtime errors if the type is incorrect. They are generally less preferred in modern .NET development.
Collection Type | Description | Use Cases |
---|---|---|
ArrayList |
A dynamic array that can grow or shrink. | When the type of elements is unknown at compile time and flexibility is paramount (though generics are preferred). |
Hashtable |
A collection of key-value pairs. | Storing data where fast lookup by a unique key is needed. |
Queue |
First-In, First-Out (FIFO) collection. | Implementing waiting lists or task queues. |
Stack |
Last-In, First-Out (LIFO) collection. | Managing call stacks or undo/redo operations. |
System.Collections.Generic
namespace whenever possible.
Generic Collections (System.Collections.Generic
)
Generic collections provide compile-time type safety and improved performance by avoiding boxing and unboxing operations.
Collection Type | Description | Use Cases |
---|---|---|
List<T> |
A strongly-typed dynamic array. | The most common and versatile collection for ordered lists of a specific type. |
Dictionary<TKey, TValue> |
A strongly-typed collection of key-value pairs. | Efficient lookup of values using a specific key type. |
HashSet<T> |
A collection of unique elements, optimized for fast lookups. | Storing unique items where order doesn't matter and checking for existence is frequent. |
Queue<T> |
A strongly-typed FIFO collection. | Implementing type-safe waiting lists. |
Stack<T> |
A strongly-typed LIFO collection. | Implementing type-safe stacks. |
List<T>
Example
// List of strings
List<string> fruits = new List<string>();
fruits.Add("Apple");
fruits.Add("Banana");
fruits.Add("Orange");
// Accessing elements
string firstFruit = fruits[0]; // "Apple"
// Adding and removing
fruits.Insert(1, "Grape"); // ["Apple", "Grape", "Banana", "Orange"]
fruits.Remove("Banana"); // ["Apple", "Grape", "Orange"]
// Iterating
foreach (string fruit in fruits)
{
Console.WriteLine(fruit);
}
Dictionary<TKey, TValue>
Example
// Dictionary mapping product IDs to names
Dictionary<int, string> products = new Dictionary<int, string>();
products.Add(101, "Laptop");
products.Add(102, "Keyboard");
// Adding using indexer (if key doesn't exist)
products[103] = "Mouse";
// Accessing values
string productName = products[101]; // "Laptop"
// Checking for keys
if (products.ContainsKey(102))
{
Console.WriteLine("Keyboard is in the dictionary.");
}
// Iterating through key-value pairs
foreach (KeyValuePair<int, string> kvp in products)
{
Console.WriteLine($"ID: {kvp.Key}, Name: {kvp.Value}");
}
Where()
, Select()
, OrderBy()
) for powerful querying and manipulation of collections. See the LINQ section for more details.
Choosing the Right Collection
The choice of array or collection depends on your specific needs:
- Use arrays for fixed-size collections of a single type when performance is critical and you know the size beforehand.
- Use
List<T>
for dynamically sized lists of a specific type. - Use
Dictionary<TKey, TValue>
for fast lookups by key. - Use
HashSet<T>
when you need to store unique items and perform fast membership checks. - Use
Queue<T>
orStack<T>
for FIFO or LIFO scenarios, respectively.
Always prioritize generic collections for type safety and better performance.