Collections in C#
Collections in C#
In .NET, collections are data structures used to store and manage groups of objects. Collections are broadly categorized into generic and non-generic based on whether they are type-safe (generic) or not (non-generic). Here's a detailed explanation of both:
When to Use Generic vs Non-Generic?
Use Generic Collections when:
Type safety is required.
Performance is a concern.
You know the types at compile time.
Use Non-Generic Collections when:
Working with older .NET versions (pre-2.0).
Interacting with APIs or libraries that return non-generic collections.
1. Non-Generic Collections
Non-generic collections are part of the System.Collections namespace. They store objects as System.Object type, meaning they lack type safety. Developers often need to cast the objects to their actual types during retrieval, which can lead to runtime errors.
Common Non-Generic Collections
ArrayList
Stores elements as object.
Automatically resizes as elements are added or removed.
Example:
ArrayList arrayList = new ArrayList();
arrayList.Add(1);
arrayList.Add("Two");
arrayList.Add(3.5);
// Retrieving requires casting
int first = (int)arrayList[0];
HashTable
The Hashtable class represents a collection of key-and-value pairs that are organized based on the hash code of the key. It uses the key to access the elements in the collection.
Ex:
Hashtable ht = new Hashtable();
ht.Add("001", "Zara Ali");
ht.Add("002", "Abida Rehman");
ICollection key = ht.Keys;
foreach (string k in key) {
Console.WriteLine(k + ": " + ht[k]);
}
Console.ReadKey();
ArrayList vs HashTable
1.ArrayList represents the ordered collection of an object or it can be said that it is individually indexed whereas a Hash table uses a key to access the elements in the collection.
2.ArrayList is used when you want to access the elements by using index whereas Hash table is used when you must access elements by using an index.
Stack
Last-In-First-Out (LIFO) collection.
Example:
Stack stack = new Stack();
stack.Push(1);
stack.Push("Two");
var item = stack.Pop(); // Requires casting
Queue
First-In-First-Out (FIFO) collection.
Example:
Queue queue = new Queue();
queue.Enqueue(1);
queue.Enqueue("Two");
var item = queue.Dequeue(); // Requires casting
Limitations of Non-Generic Collections
Type Safety: They store objects as object, requiring explicit casting when retrieving.
Performance: Boxing and unboxing occur when storing and retrieving value types, affecting performance.
Error-Prone: Casting may cause runtime errors if the wrong type is used.
2. Generic Collections
Generic collections are part of the System.Collections.Generic namespace. They are type-safe, meaning they work with specific types and eliminate the need for casting.
Advantages of Generic Collections
Type Safety: Ensures only the specified type can be stored.
Performance: Avoids boxing and unboxing, reducing overhead.
Compile-Time Errors: Type mismatches are caught at compile time.
Common Generic Collections
List<T>
Dynamic array that grows as needed.
Type-safe and strongly typed.
Example:
List<int> numbers = new List<int>();
numbers.Add(1);
numbers.Add(2);
int first = numbers[0];
Dictionary<TKey, TValue>
Key-value pair storage with unique keys.
Dictionary<int, string> dictionary = new Dictionary<int, string>();
dictionary.Add(1, "One");
dictionary.Add(2, "Two");
string value = dictionary[1];
Stack<T>
Generic LIFO collection.
Example:
Stack<string> stack = new Stack<string>();
stack.Push("First");
stack.Push("Second");
string item = stack.Pop();
Queue<T>
Generic FIFO collection.
Example:
Queue<double> queue = new Queue<double>();
queue.Enqueue(1.1);
queue.Enqueue(2.2);
double item = queue.Dequeue();
HashSet<T>
Stores unique elements and prevents duplicates.
Example:
HashSet<int> set = new HashSet<int>();
set.Add(1);
set.Add(2);
set.Add(1); // Duplicate, won't be added
SortedList<TKey, TValue>
Maintains key-value pairs in sorted order.
SortedList<int, string> sortedList = new SortedList<int, string>();
sortedList.Add(2, "Two");
sortedList.Add(1, "One");
SortedList
SortedList sl = new SortedList();
sl.Add("001", "Zara Ali");
sl.Add("002", "Abida Rehman");
Stack
BitArray
It represents an array of the binary representation using the values 1 and 0.
String vs StringBuilder
String is immutable and StringBuilder is mutable
Array:
In C#, an array is a collection of elements of the same type stored in contiguous memory locations. It is a fixed-size, strongly typed data structure provided by the language, useful for storing multiple values of the same type.
Key Features of Arrays
Fixed Size: Once an array is created, its size cannot be changed.
Strongly Typed: All elements in the array must be of the same type.
Zero-Based Indexing: Array indices start at 0.
Reference Type: Arrays are reference types in C# and derive from the System.Array class.
Contiguous Memory: Elements are stored in adjacent memory locations.
Declaring and Initializing Arrays
1. Declaration
An array is declared using square brackets ([]):
int[] numbers; // Declaration of an integer array
2. Initialization
You can initialize an array using:
Size (to define the length):
numbers = new int[5]; // Creates an array of size 5
Values (to directly assign elements):
int[] numbers = { 1, 2, 3, 4, 5 };
Combination
int[] numbers = new int[5] { 1, 2, 3, 4, 5 };
3. Default Values
When an array is initialized, all elements are set to the default value of the array's data type:
int → 0
float → 0.0
bool → false
string → null
Accessing Elements
Use the index to access or modify elements:
int[] numbers = { 10, 20, 30, 40, 50 };
int first = numbers[0]; // Access first element (10)
numbers[1] = 25; // Modify second element to 25
Important Points
Accessing an invalid index throws a System.IndexOutOfRangeException.
Types of Arrays
1. Single-Dimensional Array
A one-dimensional array stores elements in a linear form.
int[] numbers = { 1, 2, 3, 4, 5 };
2. Multi-Dimensional Array
Arrays with more than one dimension.
a. Rectangular Arrays
Each row has the same number of columns.
int[,] matrix = new int[3, 2] { { 1, 2 }, { 3, 4 }, { 5, 6 } };
// Access element at row 1, column 2
int value = matrix[0, 1]; // 2
b. Jagged Arrays
An array of arrays, where each sub-array can have a different size.
var numbers = new[] { 1, 2, 3, 4 }; // Inferred as int[]
3. Implicitly Typed Arrays
Arrays where the type is inferred by the compiler.
var numbers = new[] { 1, 2, 3, 4 }; // Inferred as int[]
Common Operations on Arrays
1. Iterating Over an Array
int[] numbers = { 1, 2, 3, 4, 5 };
// 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);}
2. Sorting
int[] numbers = { 5, 3, 8, 1 };
Array.Sort(numbers); // Sorts the array in ascending order
3. Searching
int[] numbers = { 1, 2, 3, 4, 5 };
int index = Array.IndexOf(numbers, 3); // Returns the index of the element (2)
4. Copying
int[] numbers = { 1, 2, 3 };
int[] copy = new int[3];
Array.Copy(numbers, copy, numbers.Length);
5. Reversing
int[] numbers = { 1, 2, 3 };
Array.Reverse(numbers); // { 3, 2, 1 }
Advanced Concepts
1. Length and Rank
Length: Total number of elements.
int[] numbers = { 1, 2, 3, 4, 5 };
Console.WriteLine(numbers.Length); // 5
Rank: Number of dimensions.
int[,] matrix = new int[3, 2];
Console.WriteLine(matrix.Rank); // 2
2. Bounds
GetUpperBound: Gets the upper bound of a dimension.
int[,] matrix = new int[3, 2];
int lastRow = matrix.GetUpperBound(0); // 2
int lastCol = matrix.GetUpperBound(1); // 1
Limitations of Arrays
Fixed Size: Cannot grow or shrink dynamically.
Inefficient Insert/Delete: Adding or removing elements is cumbersome.
No Built-In High-Level Operations: Unlike collections like List<T>, arrays lack methods like Add.
When to Use Arrays?
Use arrays when:
The size of the collection is known and fixed.
Performance is critical, as arrays provide faster access than collections like List<T>.
Prefer collections (List<T>, Dictionary<TKey, TValue>, etc.) for dynamic or complex data structures.
Example Program
using System;
class Program
{
static void Main()
{
// Single-dimensional array
int[] numbers = { 10, 20, 30, 40, 50 };
Console.WriteLine("Array Elements:");
foreach (int number in numbers)
{
Console.WriteLine(number);
}
// Multi-dimensional array
int[,] matrix = {
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 }
};
Console.WriteLine("\nMatrix Elements:");
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
Console.Write(matrix[i, j] + " ");
}
Console.WriteLine();
}
}
}
Comments
Post a Comment