C#
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Object-Oriented C#
-
Section 4: Working with Data
-
Section 5: Error Handling
-
Section 6: Delegates and Events
-
Section 7: Async Programming
-
Section 8: More Language Features
-
Section 9: File I/O and Serialization
-
Section 10: Networking in .NET
-
Section 11: The .NET Ecosystem
-
Section 12: Memory and Performance
-
Section 13: Concurrency Beyond Async
-
Section 14: Reflection and Attributes
-
Section 15: Testing and Best Practices
-
Section 16: Design Patterns in C#
-
Section 17: Standard Library Deep Dive
-
Section 18: Data Structures and Algorithms in C#
-
Section 19: GUI and Desktop Development Overview
-
Section 20: Practical Projects
-
Section 21: More Practice Exercises
-
Section 22: More Standard Library and Text Processing
-
Section 23: More Design Patterns
-
Section 24: More Projects
-
Section 25: Interview Practice
-
Section 26: C# Keywords Reference (Modifiers)
-
Section 27: C# Keywords Reference (Statements)
-
Section 28: C# Keywords Reference (Operators)
-
Section 29: BCL: System.Collections.Generic
-
Section 30: BCL: System.Linq
-
Section 31: BCL: System.Threading
-
Section 32: BCL: System.IO
-
Section 33: BCL: System.Text and System.Text.Json
-
Section 34: BCL: System.Net.Http
-
Section 35: C# Language Specification Topics
-
Section 36: More Practice Exercises
-
Section 37: More Async Patterns
-
Section 38: More BCL: System.Reflection and System.Diagnostics
-
Section 39: Nullable Reference Types In Depth
-
Section 40: C# Records and Pattern Matching In Depth
-
Section 41: Dependency Injection Deep Dive
-
Section 42: More Interview and Whiteboard Practice
32: Collections: List, Dictionary, HashSet
A few years ago, I was reviewing code for a junior dev who was building a simple inventory system for a warehouse app. He had used a standard array to store the product IDs. It worked fine during the demo with five items, but as soon as we hit the staging environment with thousands of products, the app crawled to a halt. Why? Because every time he wanted to check if an item existed, he was running a for loop through the entire array. He was essentially asking the computer to read a whole book from page one every time he wanted to find a single word. It was a classic case of using the wrong tool for the job.
In C#, arrays are great when you know exactly how many elements you have and that number never changes. But in the real world, data is messy. It grows, it shrinks, and you often need to find things instantly without looping. That's where the System.Collections.Generic namespace comes in.
The Flexibility of Dynamic Lists
Most of the time, when you think "I need a list of things," you want a List<T>. Unlike an array, a List doesn't require a fixed size up front. It handles the resizing logic under the hood, so you can just keep calling .Add() until you run out of RAM.
var players = new List<string>();
players.Add("Alice");
players.Add("Bob");
players.Add("Charlie");
// Removing is just as easy
players.Remove("Bob");
Console.WriteLine($"We have {players.Count} players online.");
I usually tell people to treat List<T> as their default choice. If you don't have a specific reason to use something else, start here. Just keep in mind that searching for an item in a list still requires a linear scan (O(n) for the math nerds), so if your list grows to ten thousand items, .Contains() will start to slow you down.
Instant Lookups with Dictionaries
When you need to associate a piece of data with a unique identifier—like a User ID mapped to a User object—you want a Dictionary<TKey, TValue>. This is a "hash map," and it's incredibly fast. Instead of looping through every entry, the dictionary uses a hash of the key to jump directly to the value.
var inventory = new Dictionary<string, int>
{
{ "Apple", 50 },
{ "Banana", 100 },
{ "Orange", 20 }
};
// The "pro" way to get a value without risking a KeyNotFoundException
if (inventory.TryGetValue("Apple", out int count))
{
Console.WriteLine($"We have {count} apples.");
}
One thing to watch out for: keys must be unique. If you try to .Add() a key that already exists, C# will throw an exception. If you're not sure if the key exists, use TryGetValue as shown above, or use the indexer (inventory["Apple"] = 60) which will either update the existing value or create a new one.
Filtering Duplicates with HashSets
Sometimes you don't need a value associated with a key; you just need to know if something exists in a group, and you want to make sure nothing is in there twice. That's exactly what a HashSet<T> is for. It's essentially a List that forbids duplicates and provides the same lightning-fast lookup speed as a Dictionary.
var uniqueVisitorIds = new HashSet<int>();
uniqueVisitorIds.Add(101);
uniqueVisitorIds.Add(102);
uniqueVisitorIds.Add(101); // This will be ignored; it's already there.
Console.WriteLine(uniqueVisitorIds.Count); // Output: 2
I use HashSet all the time when I'm processing logs or API responses where the source might send me the same record multiple times. Instead of writing a complex loop to check if an item is already present before adding it, I just dump everything into a HashSet and let the collection handle the deduplication for me.
📋 Practical Task
Exercise: Building a Unique Guest List and RSVP Tracker
You are tasked with creating a simple guest management system for an event. The system needs to handle two specific requirements: ensuring no guest is added twice and keeping track of each guest's meal preference.
Requirements:
- Create a
HashSet<string>to store the names of guests who have confirmed their attendance. - Create a
Dictionary<string, string>where the key is the guest's name and the value is their meal choice (e.g., "Vegan", "Beef", "Fish"). - Write a method
ProcessRSVP(string name, string meal)that:- Attempts to add the guest name to the
HashSet. - If the guest was successfully added (meaning they weren't already on the list), add their name and meal preference to the
Dictionary. - If the guest was already present, print a message saying "Guest [name] is already registered."
- Attempts to add the guest name to the
- Test your system by adding "Alice" with "Vegan", "Bob" with "Beef", and then trying to add "Alice" again with "Fish".
- Finally, print the total number of unique guests and the meal preference for "Bob".
There are no comments for now.