C# provides powerful and flexible data structures known as Collections to store and manage groups of related objects. Additionally, with the introduction of Generics in .NET 2.0, type safety and performance in collection handling have improved significantly. This tutorial explores the most commonly used collection types in C# including List, Dictionary, HashSet, Stack, Queue, and explains how to work with Generics, create generic classes and methods, and use constraints.
Collections are classes provided in the System.Collections and System.Collections.Generic namespaces that allow you to store multiple items. Unlike arrays, collections are dynamic in nature, meaning they can grow or shrink as needed.
List is a generic replacement for the ArrayList class. It stores elements of a specific type and supports methods such as Add, Remove, Contains, etc.
using System.Collections.Generic;
List<string> names = new List<string>();
names.Add("John");
names.Add("Alice");
names.Add("Bob");
foreach (string name in names)
{
Console.WriteLine(name);
}
Dictionary stores data as key/value pairs, where keys must be unique.
Dictionary<int, string> users = new Dictionary<int, string>();
users.Add(1, "Alice");
users.Add(2, "Bob");
Console.WriteLine(users[1]); // Output: Alice
HashSet stores unique elements and ignores duplicates automatically.
HashSet<int> numbers = new HashSet<int>();
numbers.Add(10);
numbers.Add(20);
numbers.Add(10); // Duplicate, will not be added
foreach (int num in numbers)
{
Console.WriteLine(num);
}
Stack follows Last-In-First-Out. You use Push and Pop methods to manage data.
Stack<string> history = new Stack<string>();
history.Push("Page1");
history.Push("Page2");
Console.WriteLine(history.Pop()); // Output: Page2
Queue follows First-In-First-Out. You use Enqueue and Dequeue methods.
Queue<string> queue = new Queue<string>();
queue.Enqueue("Customer1");
queue.Enqueue("Customer2");
Console.WriteLine(queue.Dequeue()); // Output: Customer1
List<int> scores = new List<int> { 90, 85, 75 };
scores.Insert(1, 88); // Insert 88 at index 1
scores.Remove(75); // Remove value 75
bool exists = scores.Contains(90);
Generics allow you to define a class, method, or interface with a placeholder for the data type. It enhances reusability and type safety without sacrificing performance.
public class Box<T>
{
public T Value;
public void Display()
{
Console.WriteLine("Value: " + Value);
}
}
Box<int> intBox = new Box<int>();
intBox.Value = 123;
intBox.Display();
Box<string> strBox = new Box<string>();
strBox.Value = "Hello Generics";
strBox.Display();
public void Swap<T>(ref T a, ref T b)
{
T temp = a;
a = b;
b = temp;
}
int x = 5, y = 10;
Swap<int>(ref x, ref y);
Console.WriteLine($"x = {x}, y = {y}");
Constraints restrict the types that can be used as arguments for a generic class or method.
public class Repository<T> where T : class, new()
{
public T Create()
{
return new T();
}
}
Generic interfaces provide a blueprint for reusable components that work with any data type.
public interface IContainer<T>
{
void Add(T item);
T Get();
}
List<string> cities = new List<string> { "Delhi", "Chennai", "Kolkata" };
IEnumerable<string> query = from c in cities
where c.StartsWith("C")
select c;
foreach (var city in query)
{
Console.WriteLine(city);
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Catalog<T> where T : class
{
private List<T> items = new List<T>();
public void AddItem(T item)
{
items.Add(item);
}
public List<T> GetAll()
{
return items;
}
}
Catalog<Product> productCatalog = new Catalog<Product>();
productCatalog.AddItem(new Product { Id = 1, Name = "Laptop" });
productCatalog.AddItem(new Product { Id = 2, Name = "Mobile" });
foreach (var item in productCatalog.GetAll())
{
Console.WriteLine($"{item.Id}: {item.Name}");
}
| Feature | Generics | Non-Generics |
|---|---|---|
| Type Safety | Yes | No |
| Performance | High | Low (Boxing/Unboxing) |
| Flexibility | High | Limited |
| Compile-Time Checking | Yes | No |
C# Collections and Generics form the backbone of many data processing applications. They offer flexibility, performance, and type safety, which are critical for robust software development. Understanding and applying the right collection type and using generics effectively can make your code more readable, efficient, and maintainable.
Copyrights © 2024 letsupdateskills All rights reserved