A collection in C# is a data structure used to store multiple items, typically of the same type, in an organized manner. Collections are useful for grouping objects or data elements together so that they can be easily manipulated, iterated, and accessed.
A List< T > in C# is a generic collection type that represents a dynamic array.
The T in List< T > denotes the type of elements the list will store, allowing you to define a list of any type (e.g., List< int >, List< string >, List< Player >).
int[] numbers = { 1, 2, 3, 4, 5 };
foreach (var num in numbers)
{
Console.WriteLine(num);
}
// 1. list (unlike array which is fixed, it can change size dynamically)
List<string> names = new List<string> { "Alice", "Bob", "Charlie" };
names.Add("Dave"); // add name
names.Remove("Bob"); // remove name
foreach (var name in names)
{
Console.WriteLine(name); // new list for names
}
A Stack in C# is a collection type that represents a Last-In-First-Out (LIFO) data structure. This means that the last element added to the stack is the first one to be removed, similar to how items are stacked in real life (e.g., a stack of plates where you add plates to the top and remove them from the top).
Stack stack = new Stack();
stack.Push(1);
stack.Push(2);
stack.Push(3);
while (stack.Count > 0)
{
Console.WriteLine(stack.Pop());
}
// output:
// 3
// 2
// 1
A Queue in C# is a collection type that represents a First-In-First-Out (FIFO) data structure. This means that the first element added to the queue will be the first one to be removed, similar to how a queue works in real life (e.g., standing in line at a bank where the first person in line is the first to be served).
Queue queue = new Queue();
queue.Enqueue(1);
queue.Enqueue(2);
queue.Enqueue(3);
while (queue.Count > 0)
{
Console.WriteLine(queue.Dequeue());
}
// output:
// 1
// 2
// 3
ArrayList is a non-generic collection in C# that can store elements of any type as objects. It allows dynamic resizing, meaning its size can grow or shrink as needed.
arrayList.Add("Hello"); // string
arrayList.Add(3.14); // float
Console.WriteLine("ArrayList: ");
foreach (var item in arrayList)
{
Console.WriteLine(item);
}
arrayList.Remove(1);
Console.WriteLine("\nArrayList w/ remove: ");
foreach (var item in arrayList)
{
Console.WriteLine(item);
}
A Hashtable in C# is a collection that stores key-value pairs, similar to a dictionary.
Hashtable is outdated and has been replaced by the generic Dictionary<TKey, TValue>, which is more efficient and type-safe.
// key-value collection
Hashtable hashtable = new Hashtable();
// add key-value
hashtable["Alice"] = 25;
hashtable["Bob"] = 30;
hashtable["Potion"] = 20;
Console.WriteLine("Hashtable: ");
foreach(DictionaryEntry entry in hashtable)
{
Console.WriteLine($"Key: {entry.Key}, Value: {entry.Value}");
}
// specific key
Console.WriteLine($"\nAlice Age: {hashtable["Alice"]}");
// remove key
hashtable.Remove("Bob");
Console.WriteLine("Hashtable: ");
foreach (DictionaryEntry entry in hashtable)
{
Console.WriteLine($"Key : {entry.Key}, Value : {entry.Value}");
}
A Generic in C# allows you to define classes, interfaces, methods, and collections with a placeholder type. This means you can write reusable and type-safe code that works with any data type without specifying the type upfront.
Generics are mainly used to avoid redundant code, improve performance, and ensure type safety.
using System;
class Program
{
// Generic method (T is a placeholder for any type)
static void Print<T>(T value)
{
Console.WriteLine(value);
}
static void Main()
{
Print<int>(10); // Works for int
Print<string>("Hello"); // Works for string
}
}
class Cup<T>
{
public T Content { get; set; }
}
static void Main(string[] args)
{
Cup<string> cupOfString = new Cup<string> { Content = "Coffee" };
Cup<int> cupOfInt = new Cup<int> { Content = 42 };
Console.WriteLine($"CupOfString: {cupOfString.Content}");
Console.WriteLine($"cupOfInt: {cupOfInt.Content}");
// w/ stack
Stack<int> stack = new Stack<int>();
stack.Push(10);
stack.Push(20);
stack.Push(30);
while (stack.Count > 0)
{
Console.WriteLine(stack.Pop());
}
// w/ list
List<string> names = new List<string> { "Alice", "Bob", "Charlie" };
names.Add("Dave");
foreach (var name in names)
{
Console.WriteLine(name);
}
}
IEnumerator is an interface in C# that allows iteration over a collection one element at a time.
using System;
using System.Collections;
using System.Collections.Generic;
class Program
{
static void Main()
{
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
// Getting an IEnumerator from the list
IEnumerator<int> enumerator = numbers.GetEnumerator();
// Iterating manually
while (enumerator.MoveNext()) // Moves to the next element
{
Console.WriteLine(enumerator.Current); // Prints current element
}
}
}
// output:
1
2
3
4
5
A Dictionary is a collection that stores key-value pairs. Each word (key) has a definition (value). You can quickly find a value using its key.
Dictionary<string, int> scores = new Dictionary<string, int>();
// Adding key-value pairs
scores["Alice"] = 95;
scores["Bob"] = 88;
scores["Charlie"] = 92;
// Accessing values by key
Console.WriteLine($"Alice's score: {scores["Alice"]}"); // output: 95
LINQ (Language Integrated Query) is a feature in C# that allows you to query collections in a readable and concise way, similar to SQL queries. It works with arrays, lists, databases, XML, and more.
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
// Traditional way (without LINQ)
List<int> evenNumbers = new List<int>();
foreach (int num in numbers)
{
if (num % 2 == 0)
evenNumbers.Add(num);
}
// LINQ way (simpler)
var evenNumbersLinq = numbers.Where(n => n % 2 == 0).ToList();
// Example
int[] numbers = { 1, 2, 3, 4, 5 };
var evenNumbers = numbers.Where(n => n % 2 == 0);
foreach(var num in evenNumbers)
{
Console.WriteLine(num);
}