C# & .NET Framework Collections & LINQ Magic
💡
Exercise 41

Generics & List<T> 15 XP Medium

Ctrl+Enter Run Ctrl+S Save

The Architect's Type-Safe Registry 🏢

Every great city needs a resident registry — but imagine the chaos if someone accidentally registered a lamppost as a citizen! In old .NET (pre-generics), collections like ArrayList stored everything as object, meaning you could mix strings, integers, and toasters in the same list. Generics solved this by letting you declare exactly what type a collection holds, catching mistakes at compile time instead of runtime.

Why Generics Matter

Before generics (introduced in C# 2.0), developers used ArrayList from System.Collections. The problem? Everything was boxed/unboxed as object:

// OLD WAY — no type safety! ArrayList old = new ArrayList(); old.Add("Alice"); old.Add(42); // Compiles fine, but is this intentional? string name = (string)old[1]; // Runtime crash! InvalidCastException

With generics, the compiler enforces type safety at compile time, eliminating costly boxing/unboxing for value types and preventing invalid casts entirely:

// NEW WAY — type-safe! List<string> residents = new List<string>(); residents.Add("Alice"); // residents.Add(42); // Compile error! Can't add int to List<string>

List<T> — The Architect's Essential Tool

List<T> lives in System.Collections.Generic and is the most commonly used collection in C#. It's a dynamically-sized array that provides O(1) indexed access and amortized O(1) additions at the end.

  • Add(T item) — Appends an item to the end of the list
  • Remove(T item) — Removes the first occurrence; returns true if found
  • Count — Property returning the number of elements (not a method!)
  • Contains(T item) — Returns true if the item exists (uses Equals)
  • Sort() — Sorts in-place using the default comparer (alphabetical for strings)
  • Find(Predicate<T>) — Returns the first element matching the predicate, or default(T)
  • Insert(int index, T item) — Inserts at a specific position
  • RemoveAt(int index) — Removes element at the specified index
  • ForEach(Action<T>) — Executes an action on each element
List<string> residents = new List<string>(); // Adding residents to the city registry residents.Add("Alice"); residents.Add("Bob"); residents.Add("Charlie"); Console.WriteLine($"Residents: {residents.Count}"); // 3 // Check membership Console.WriteLine($"Contains Bob: {residents.Contains("Bob")}"); // True // Sort alphabetically residents.Sort(); Console.WriteLine(string.Join(", ", residents)); // Alice, Bob, Charlie // Find with a predicate string found = residents.Find(r => r.StartsWith("C")); Console.WriteLine($"Found: {found}"); // Charlie

List<T> vs ArrayList — A Performance Comparison

For value types like int, List<int> is dramatically faster than ArrayList because it avoids boxing (wrapping a value type in an object on the heap). For reference types like string, the performance difference is smaller but type safety alone makes List<T> the clear winner.

Generic Type Constraints — A Taste

You can constrain what types are allowed with the where keyword. This is a preview — we'll explore this deeper later:

// Only types that implement IComparable<T> can be used public static T FindMax<T>(List<T> items) where T : IComparable<T> { T max = items[0]; foreach (T item in items) { if (item.CompareTo(max) > 0) max = item; } return max; }

Time to build the city's resident registry, Architect! Register residents using List<T>, then query and sort the data.

📋 Instructions
**Build the City's Type-Safe Resident Registry!** 1. Create a `List` called `residents` 2. Add three residents: `"Alice"`, `"Bob"`, `"Charlie"` 3. Print `"Residents: "` followed by the count 4. Add `"Diana"` to the list and print `"Added: Diana"` 5. Print the new count as `"Residents: "` followed by the count 6. Check if `"Bob"` is in the list and print `"Contains Bob: "` followed by the result 7. Sort the list alphabetically 8. Print `"Sorted: "` followed by all residents joined with `", "`
Use `new List<string>()` to create the list. The `Count` property (not method) gives the size. `Sort()` sorts in place. Use `string.Join(", ", residents)` to create a comma-separated string.
main.py
Hi! I'm Rex 👋
Output
Ready. Press ▶ Run or Ctrl+Enter.