Start course

Structures to repeat tasks or access data collections are at the heart of compact and reusable code. C#, like other programming languages, provides three basic mechanisms allowing you to execute statements multiple times dynamically. In this course, we'll take an in-depth look at the for loop, while loop, and foreach loop.

These looping mechanisms vary in structure and intended application, and we'll examine how to use them in different scenarios. In the course of this detailed investigation, you will learn some of the potential pitfalls that accompany programming with each type of loop, how to avoid them, and create efficient loops. There are code examples demonstrating the use of each loop type in a practical way, along with other helpful C# and .NET code snippets.

Learning Objectives

  • An in-depth understanding of for loops
  • Learn about while loop syntax and see how they are used
  • Gain a foundational understanding of object lists
  • Learn how to use, and not to use, a foreach loop to iterate through a list

Intended Audience

This course is intended for those who already have a basic understanding of C# and want to learn about loops.


To get the most out of this course, you should have a basic knowledge of C# as well as an understanding of object orientation and C# classes. Please consider taking our Introduction to Object Orientation and C# Classes course before taking this one.

Source Code

Source code related to the lectures can be found here


The foreach Loop is designed explicitly for object-oriented languages and more specifically for use with lists or collections of objects that are all of the same class or share the same heritage. Its primary use case is to cycle through a list of objects, either doing something to the object or calling an object's method. Unlike a for loop or a while loop, you cannot choose to advance through the list by more than one element at a time. The purpose of foreach is to give you easy access to each list element in the form of its native class type instead of having to cast or convert an array element. This is not to say you couldn't use a for loop when the need arises, but foreach loops are convenient in most scenarios.

I wonder if you can spot the error here? Correct, Pluto is not a planet. Anyway, I have a list of strings called planets, and I'm adding the planet names to the list with the AddRange method. AddRange adds multiple elements at once, and I'm creating those elements by splitting the string literal on commas using the string Split method specifying a comma. Then I'll sort the list of strings alphabetically before writing each element to the console. No surprises here as we get the expected result. 

Let's try it with custom and more complex objects created from the planet class. Not too complex, though - a couple of properties and methods. I've overridden ToString, returning the planet name with its distance from the sun. The print method will write the planet name across the console proportionate to the distance from the sun. 

When I run the program Console.WriteLine uses the overridden ToString method.  I still want to remove Pluto from the planets list. I'll try the list remove method. This won't work as remove expects a planet object, not the planet's name. I'll have to loop through the list, find the planet object with the name matching Pluto, and then remove it. That looks about right. Let's try it.

Okay, that didn't work, and the error message tells us that we've modified the list, which is true; we have by removing an element. This error illustrates a crucial aspect of lists and by association foreach loops.

At the most fundamental level, in terms of how data is stored and structured, a list is an array. Arrays are immutable, meaning you can change the data they store but not their structure, that is, the number of elements. You can change the size of an array by creating a new array with a new size and copying the element data to it. The array method resize does this for you. From a computational point of view, this is an expensive task. In the interests of simplicity and convenience, .NET wrapped the array structure in a list object with methods for adding and removing elements. A list is not descended from an array as in inheritance. It just means a list uses an array internally to store data. You might be thinking, "if a list is really an array, and you can't easily resize an array, how does the list add method work?" Well, the big reveal is a little disappointing. It does resize the array, but each time the add method is called, the array will double in size if the current capacity can't accommodate the new element. This means as the list grows less resize operations will take place. The list class has a property called capacity, the size of the allocated array, and count, which is the number of elements containing valid data. Long story short, a list is more convenient, but the convenience comes at a slight performance price. You can mitigate the initial resize performance hit by specifying an initial list size if you have some idea how big it will be.

Removing an item from a list means copying all subsequent items back one element, changing data positions within the array so the array has no gaps. We can walk through a list with a for-loop using an index and use the RemoveAt method, saying remove the element at this position. RemoveAt copies the following items back one and adjusts the count property. The foreach loop isn't re-evaluating the list count on each iteration so as to improve performance, hence the error.

After removing Pluto, I'll display the solar system planets at relative distance from the sun. The print method takes the planet next closest to the sun and subtracts its distance from the sun to work out where it should start printing its own name. I'll need to specify the planet next closest to the sun as a parameter to the print method, and I can do that by setting innerPlanet, which is of type planet, to the current planet after calling the print method. The first time through the loop, innerPlanet is null as there is no planet between Mercury and the sun.

About the Author
Learning Paths

Hallam is a software architect with over 20 years experience across a wide range of industries. He began his software career as a  Delphi/Interbase disciple but changed his allegiance to Microsoft with its deep and broad ecosystem. While Hallam has designed and crafted custom software utilizing web, mobile and desktop technologies, good quality reliable data is the key to a successful solution. The challenge of quickly turning data into useful information for digestion by humans and machines has led Hallam to specialize in database design and process automation. Showing customers how leverage new technology to change and improve their business processes is one of the key drivers keeping Hallam coming back to the keyboard. 

Covered Topics