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
15: Arrays and Collections Basics
Up until now, we've been dealing with single pieces of data. That's fine for a username or a score, but real software is almost always about managing groups of things. Whether it's a list of users in a database or a collection of enemies in a game level, you need a way to store multiple values without creating a hundred differently-named variables.
Setting up fixed quest slots
Let's imagine we're building a simple RPG. I want the player to have a limited number of "Active Quest" slots. Since the limit is strict (say, only 3 quests at a time), a standard Array is the perfect tool. Arrays are great when you know exactly how many items you need and that number isn't going to change while the program is running.
string[] activeQuests = new string[3];
activeQuests[0] = "Find the Lost Sword";
activeQuests[1] = "Deliver the Letter";
activeQuests[2] = "Slay the Slime";
I'm declaring the type as string[], which tells C# this is an array of strings. By putting [3] in the initializer, I've locked the size. It's efficient, but it's rigid.
Hitting the boundary wall
Here is where I usually trip up when I'm rushing through a prototype. I might forget that arrays are zero-indexed and try to add one more item than I allocated. Watch what happens when I try to add a fourth quest to our three-slot array:
activeQuests[3] = "Rescue the Prince";
// Boom. IndexOutOfRangeException.
I just tried to put something in the fourth slot, but the array only goes from index 0 to 2. The program crashes immediately. In a professional environment, this is a bug that gets flagged in code review instantly. The lesson here is that arrays are dangerous if your data size is unpredictable.
Switching to a dynamic quest log
For a "Completed Quests" list, a fixed array makes no sense. We don't know if the player will finish two quests or two hundred. This is where List<T> comes in. Lists are like arrays that can grow and shrink on the fly. They are part of the System.Collections.Generic namespace, which you'll see at the top of almost every C# file.
List<string> completedQuests = new List<string>();
completedQuests.Add("Find the Lost Sword");
completedQuests.Add("Deliver the Letter");
completedQuests.Add("Explore the Caves");
completedQuests.Add("Talk to the Mayor");
Notice I didn't have to specify a size. I just keep calling .Add(), and C# handles the memory management behind the scenes. It's slightly more overhead than a raw array, but for 90% of your work, the flexibility is worth the trade-off.
Printing the final list
Now that we have our data, we need to show it to the player. While you can use a for loop with an index, the foreach loop is much cleaner when you just need to visit every item in a collection without caring about the specific index number.
Console.WriteLine("Your completed quests:");
foreach (string quest in completedQuests)
{
Console.WriteLine($"- {quest}");
}
I prefer foreach because it's harder to make a "fencepost error" (off-by-one error) since you aren't manually managing the counter. You're just telling C#, "Give me every item in this list, one by one, until you hit the end."
📋 Practical Task
Build a High Score Tracker
Create a program that manages a leaderboard for a game. Your task is to:
- Initialize a
List<int>to store player scores. - Add five different integer scores to the list.
- Remove the lowest score from the list (Hint: look at the
.Remove()or.RemoveAt()methods). - Use a
foreachloop to print all the remaining scores to the console, each on a new line.
There are no comments for now.