.NET Lists
Introduction
Lists are one of the most commonly used data structures in .NET programming. Unlike arrays which have a fixed size, lists are dynamic collections that can grow or shrink in size as needed. In .NET, the List<T>
class provides a powerful and flexible way to store and manipulate collections of objects, where T
represents the type of elements in the list.
Lists are part of the System.Collections.Generic
namespace and offer numerous methods and properties to add, remove, search, and sort elements. Whether you're building a simple console application or a complex web service, understanding how to work with lists is an essential skill for any .NET developer.
Creating Lists
Let's start by learning how to create a list in C#:
// Import the necessary namespace
using System.Collections.Generic;
// Create an empty list of integers
List<int> numbers = new List<int>();
// Create a list with initial capacity
List<string> names = new List<string>(10);
// Create a list with initial values
List<double> prices = new List<double> { 19.99, 29.99, 39.99 };
The <T>
in List<T>
represents the type parameter - it specifies what type of elements the list will contain. You can create lists of any type, including built-in types (like int
, string
, bool
) and custom classes or structs.
Basic List Operations
Adding Elements
You can add elements to a list using the Add
method or AddRange
for multiple items:
List<string> fruits = new List<string>();
// Add individual items
fruits.Add("Apple");
fruits.Add("Banana");
fruits.Add("Cherry");
// Output: Count = 3
Console.WriteLine($"Count = {fruits.Count}");
// Add multiple items at once
fruits.AddRange(new string[] { "Orange", "Mango", "Pineapple" });
// Output: Count = 6
Console.WriteLine($"Count = {fruits.Count}");
Accessing Elements
You can access list elements by index, just like with arrays:
List<string> fruits = new List<string> { "Apple", "Banana", "Cherry" };
// Access the first element (index 0)
string firstFruit = fruits[0];
Console.WriteLine(firstFruit); // Output: Apple
// Access the last element
string lastFruit = fruits[fruits.Count - 1];
Console.WriteLine(lastFruit); // Output: Cherry
Removing Elements
Lists offer several ways to remove elements:
List<string> fruits = new List<string> { "Apple", "Banana", "Cherry", "Banana", "Mango" };
// Remove a specific element (first occurrence)
fruits.Remove("Banana");
// Now: Apple, Cherry, Banana, Mango
// Remove element at specific index
fruits.RemoveAt(1);
// Now: Apple, Banana, Mango
// Remove a range of elements (starting index, count)
fruits.RemoveRange(0, 1);
// Now: Banana, Mango
// Clear all elements
fruits.Clear();
// Now: empty list
Searching and Checking
Lists provide methods to search for elements and check for their existence:
List<int> numbers = new List<int> { 10, 20, 30, 40, 50, 30 };
// Check if an element exists
bool contains30 = numbers.Contains(30);
Console.WriteLine($"Contains 30: {contains30}"); // Output: Contains 30: True
// Find the index of the first occurrence
int firstIndex = numbers.IndexOf(30);
Console.WriteLine($"First index of 30: {firstIndex}"); // Output: First index of 30: 2
// Find the index of the last occurrence
int lastIndex = numbers.LastIndexOf(30);
Console.WriteLine($"Last index of 30: {lastIndex}"); // Output: Last index of 30: 5
// Check if any element satisfies a condition
bool hasEvenNumber = numbers.Exists(n => n % 2 == 0);
Console.WriteLine($"Has even number: {hasEvenNumber}"); // Output: Has even number: True
Iterating Through Lists
You can iterate through a list using several approaches:
List<string> colors = new List<string> { "Red", "Green", "Blue", "Yellow" };
// Using for loop
Console.WriteLine("Using for loop:");
for (int i = 0; i < colors.Count; i++)
{
Console.WriteLine(colors[i]);
}
// Using foreach loop (recommended)
Console.WriteLine("\nUsing foreach loop:");
foreach (string color in colors)
{
Console.WriteLine(color);
}
// Using ForEach method with a lambda expression
Console.WriteLine("\nUsing ForEach method:");
colors.ForEach(color => Console.WriteLine(color));
Sorting and Transforming Lists
Lists can be sorted and transformed using various methods:
List<int> numbers = new List<int> { 5, 2, 8, 1, 7, 3 };
// Sort the list in ascending order
numbers.Sort();
Console.WriteLine("Sorted: " + string.Join(", ", numbers));
// Output: Sorted: 1, 2, 3, 5, 7, 8
// Reverse the order
numbers.Reverse();
Console.WriteLine("Reversed: " + string.Join(", ", numbers));
// Output: Reversed: 8, 7, 5, 3, 2, 1
// Convert all elements (using ConvertAll)
List<string> numberStrings = numbers.ConvertAll(n => $"Number: {n}");
Console.WriteLine("Converted: " + string.Join(", ", numberStrings));
// Output: Converted: Number: 8, Number: 7, Number: 5, Number: 3, Number: 2, Number: 1
Working with Complex Objects
Lists can store complex objects, not just primitive types:
// Define a simple class
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public override string ToString()
{
return $"{Name} ({Age})";
}
}
// Create and use a list of Person objects
List<Person> people = new List<Person>
{
new Person { Name = "Alice", Age = 30 },
new Person { Name = "Bob", Age = 25 },
new Person { Name = "Charlie", Age = 35 }
};
// Find a person
Person bob = people.Find(p => p.Name == "Bob");
Console.WriteLine(bob); // Output: Bob (25)
// Sort by age
people.Sort((p1, p2) => p1.Age.CompareTo(p2.Age));
Console.WriteLine("Sorted by age: " + string.Join(", ", people));
// Output: Sorted by age: Bob (25), Alice (30), Charlie (35)
// Filter people older than 25
List<Person> olderPeople = people.FindAll(p => p.Age > 25);
Console.WriteLine("People older than 25: " + string.Join(", ", olderPeople));
// Output: People older than 25: Alice (30), Charlie (35)
Real-World Examples
Example 1: Task Manager
Here's a simple task manager application that uses a list to store tasks:
public class Task
{
public string Description { get; set; }
public bool IsCompleted { get; set; }
}
public class TaskManager
{
private List<Task> tasks = new List<Task>();
public void AddTask(string description)
{
tasks.Add(new Task { Description = description, IsCompleted = false });
Console.WriteLine($"Added task: {description}");
}
public void CompleteTask(int index)
{
if (index >= 0 && index < tasks.Count)
{
tasks[index].IsCompleted = true;
Console.WriteLine($"Completed task: {tasks[index].Description}");
}
else
{
Console.WriteLine("Invalid task index.");
}
}
public void DisplayTasks()
{
if (tasks.Count == 0)
{
Console.WriteLine("No tasks.");
return;
}
Console.WriteLine("Tasks:");
for (int i = 0; i < tasks.Count; i++)
{
string status = tasks[i].IsCompleted ? "[✓]" : "[ ]";
Console.WriteLine($"{i}: {status} {tasks[i].Description}");
}
}
}
// Usage:
TaskManager manager = new TaskManager();
manager.AddTask("Learn about .NET Lists");
manager.AddTask("Complete programming assignment");
manager.AddTask("Write documentation");
manager.DisplayTasks();
manager.CompleteTask(0);
manager.DisplayTasks();
Example 2: Shopping Cart
Here's an implementation of a shopping cart using lists:
public class Product
{
public string Name { get; set; }
public decimal Price { get; set; }
public override string ToString()
{
return $"{Name}: ${Price}";
}
}
public class ShoppingCart
{
private List<Product> items = new List<Product>();
public void AddProduct(Product product)
{
items.Add(product);
Console.WriteLine($"Added {product.Name} to cart.");
}
public void RemoveProduct(int index)
{
if (index >= 0 && index < items.Count)
{
Console.WriteLine($"Removed {items[index].Name} from cart.");
items.RemoveAt(index);
}
else
{
Console.WriteLine("Invalid product index.");
}
}
public decimal CalculateTotal()
{
decimal total = 0;
foreach (var item in items)
{
total += item.Price;
}
return total;
}
public void DisplayCart()
{
if (items.Count == 0)
{
Console.WriteLine("Your cart is empty.");
return;
}
Console.WriteLine("Shopping Cart:");
for (int i = 0; i < items.Count; i++)
{
Console.WriteLine($"{i}: {items[i]}");
}
Console.WriteLine($"Total: ${CalculateTotal()}");
}
}
// Usage:
ShoppingCart cart = new ShoppingCart();
cart.AddProduct(new Product { Name = "Laptop", Price = 999.99m });
cart.AddProduct(new Product { Name = "Mouse", Price = 24.99m });
cart.AddProduct(new Product { Name = "Keyboard", Price = 59.99m });
cart.DisplayCart();
cart.RemoveProduct(1);
cart.DisplayCart();
Performance Considerations
When working with lists, keep these performance considerations in mind:
-
Initial Capacity: When you know the approximate number of elements beforehand, specify an initial capacity to reduce the number of resizing operations:
csharp// More efficient for large lists
List<int> numbers = new List<int>(10000); -
Add vs Insert: Adding to the end of a list (
Add
) is much faster than inserting at the beginning or middle (Insert
), which requires shifting elements. -
Contains vs Binary Search: For sorted lists, use
BinarySearch
instead ofContains
for better performance with large collections:csharpList<int> sortedNumbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int index = sortedNumbers.BinarySearch(7); // More efficient for sorted lists -
Clear vs New: When you need to empty a list, use
Clear()
instead of creating a new instance if you plan to reuse the list. This preserves the allocated capacity.
Summary
.NET Lists are versatile data structures that provide dynamic storage for collections of elements. They offer numerous methods for adding, removing, searching, and manipulating data, making them an essential tool in a developer's toolbox.
Key points to remember about lists:
- Lists are dynamic and can grow or shrink as needed
- They provide type safety through generic implementation (
List<T>
) - Lists offer methods for common operations like adding, removing, finding, and sorting elements
- They can store both simple types and complex objects
- Lists are indexed from 0, like arrays
Mastering lists is fundamental for effective C# and .NET development, as they are used in countless programming scenarios, from simple data management to complex application architectures.
Exercises
- Create a program that reads a list of names from the console and then prints them in alphabetical order.
- Implement a simple to-do list application that allows adding, removing, and marking tasks as complete.
- Create a program that manages a playlist of songs, allowing the user to add, remove, and shuffle songs.
- Implement a method that takes two lists and returns a new list containing only the elements that appear in both lists.
- Create a program that reads a list of numbers and calculates various statistics like minimum, maximum, average, and median.
Additional Resources
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)