On this page
Collections and LINQ
The .NET collections framework provides generic, type-safe containers. LINQ (Language Integrated Query) adds declarative querying over any IEnumerable<T>.
Lists and Arrays
var numbers = new List<int> { 1, 2, 3, 4, 5 };
numbers.Add(6);
int[] arr = { 10, 20, 30 };
Console.WriteLine($"Count: {numbers.Count}, first: {arr[0]}");
foreach (var n in numbers)
Console.Write($"{n} ");
Console.WriteLine();
Dictionary
var scores = new Dictionary<string, int>
{
["Alice"] = 95,
["Bob"] = 87,
};
scores["Charlie"] = 92;
if (scores.TryGetValue("Alice", out int score))
Console.WriteLine($"Alice: {score}");
HashSet
var unique = new HashSet<string> { "a", "b", "c" };
unique.Add("a"); // ignored
var other = new HashSet<string> { "b", "c", "d" };
unique.IntersectWith(other);
Console.WriteLine(string.Join(", ", unique)); // b, c
LINQ Query Syntax
var products = new[]
{
new { Name = "Laptop", Price = 999.99 },
new { Name = "Mouse", Price = 29.99 },
new { Name = "Keyboard", Price = 79.99 },
};
var expensive = from p in products
where p.Price > 50
orderby p.Price descending
select p.Name;
foreach (var name in expensive)
Console.WriteLine(name);
LINQ Method Syntax
var numbers = Enumerable.Range(1, 10);
var evens = numbers
.Where(n => n % 2 == 0)
.Select(n => n * n)
.ToList();
Console.WriteLine(string.Join(", ", evens)); // 4, 16, 36, 64, 100
int sum = numbers.Sum();
double avg = numbers.Average();
int max = numbers.Max();
Common LINQ Methods
| Method | Purpose |
|---|---|
Where |
Filter elements |
Select |
Transform elements |
OrderBy |
Sort ascending |
GroupBy |
Group by key |
FirstOrDefault |
First match or default |
Any / All |
Predicate checks |
LINQ queries are deferred — they execute when you iterate or call a terminal method like ToList().
Queue, Stack, and LinkedList
var queue = new Queue<string>();
queue.Enqueue("first");
queue.Enqueue("second");
Console.WriteLine(queue.Dequeue()); // first
var stack = new Stack<int>();
stack.Push(1);
stack.Push(2);
Console.WriteLine(stack.Pop()); // 2
Immutable Collections
using System.Collections.Immutable;
var builder = ImmutableList.CreateBuilder<int>();
builder.Add(1);
builder.Add(2);
var immutable = builder.ToImmutable();
// immutable.Add(3) — does not exist; returns new list
var updated = immutable.Add(3);
Use immutable collections when sharing data across threads.
Advanced LINQ
var sales = new[]
{
new { Region = "East", Amount = 100 },
new { Region = "West", Amount = 200 },
new { Region = "East", Amount = 150 },
};
var byRegion = sales
.GroupBy(s => s.Region)
.Select(g => new { Region = g.Key, Total = g.Sum(s => s.Amount) });
var top = sales.OrderByDescending(s => s.Amount).First();
var hasLarge = sales.Any(s => s.Amount > 500);
IEnumerable vs List
| Type | Materialized | Use when |
|---|---|---|
IEnumerable<T> |
No (deferred) | Passing query pipelines |
List<T> |
Yes | Random access, mutation |
IReadOnlyList<T> |
Yes | Return without allowing mutation |
Call .ToList() only when you need multiple enumeration or indexing.
Performance Tips
- Use
HashSet<T>for O(1) lookups instead ofList.Contains(). - Prefer
Dictionary.TryGetValueoverContainsKey+ indexer (one lookup vs two). - Large LINQ chains on hot paths — profile before optimizing.