DEV Community

mohamed Tayel
mohamed Tayel

Posted on

Mastering C# Fundamentals: Understanding Lists

Meta Description: Learn about the power of collections in C# with this comprehensive guide. Discover the advantages of using Lists over arrays, including dynamic sizing and type safety. Explore practical examples and tackle easy, medium, and difficult assignments to enhance your understanding of managing collections in C# effectively

If you've worked with arrays, you're already familiar with creating lists of data. Arrays allow you to store a fixed-size list of elements of a specific type, like integers or custom objects such as employees. However, arrays come with limitations: they have a fixed size, and their operations are not very flexible. That's where collections come in, particularly the List class, which offers a dynamic, flexible way to manage lists of data.

The List class is part of the .NET collection framework. It allows you to add, remove, and manage elements in a dynamic way without worrying about specifying the initial size. Lists are also generic, meaning they help maintain type safety. Let's explore these concepts in more detail.

Declaring and Using Lists

Here is an example of creating a list of integers in C#:

List<int> productIds = new List<int>();
Enter fullscreen mode Exit fullscreen mode

In the above code:

  • List<int> creates a list that can store integers.
  • The angle brackets (<>) specify that we are creating a list of a certain type—in this case, integers.
  • This ensures type safety, meaning only integers can be added to the list, which prevents runtime errors.

After defining a list, you can use its built-in methods to manipulate the data it stores:

productIds.Add(101);     // Adding an element
productIds.Add(102);
productIds.Remove(101);  // Removing an element
int count = productIds.Count;  // Getting the number of items
Enter fullscreen mode Exit fullscreen mode

The Add, Remove, and Count methods make Lists very practical and easy to use compared to arrays, as they handle resizing automatically.

Lists Are Dynamic

One of the significant benefits of using Lists is their dynamic sizing. Unlike arrays, lists don’t require an initial size, which means they will grow as needed. You don't have to worry about copying over elements to a larger array manually when the collection grows beyond its initial capacity.

Type Safety

The generic nature of List helps maintain type safety. If you try to add an incompatible type to a list (e.g., adding a string to a list of integers), the compiler will catch the error:

productIds.Add("not an integer"); // Compile-time error
Enter fullscreen mode Exit fullscreen mode

This ensures that errors are caught early, providing a more robust and error-free coding experience.

Practical Examples

To better understand how lists work, let's take some practical examples in different scenarios. We'll also include assignments for three levels—easy, medium, and difficult.

Example 1: Managing Product Inventory

Suppose you are managing product inventory, and each product has a unique identifier. You can use a list to store these identifiers and easily add, remove, or check inventory.

List<int> productInventory = new List<int> { 1, 2, 3, 4, 5 };

// Add a new product
productInventory.Add(6);

// Remove a product
productInventory.Remove(3);

// Check if a product exists
bool hasProduct = productInventory.Contains(2); // Returns true

// Get the total number of products
Console.WriteLine($"Total products: {productInventory.Count}");
Enter fullscreen mode Exit fullscreen mode

Example 2: Managing Employees

Now let’s consider a slightly more complex example—managing a list of employees. You can create a class Employee and use a list to store multiple employees:

public class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }

    public Employee(int id, string name)
    {
        Id = id;
        Name = name;
    }
}

List<Employee> employees = new List<Employee>
{
    new Employee(1, "Alice"),
    new Employee(2, "Bob"),
    new Employee(3, "Charlie")
};

// Add a new employee
employees.Add(new Employee(4, "David"));

// Remove an employee by finding them first
Employee toRemove = employees.FirstOrDefault(e => e.Id == 2);
if (toRemove != null)
{
    employees.Remove(toRemove);
}

// Display all employee names
foreach (var employee in employees)
{
    Console.WriteLine($"Employee: {employee.Name}");
}
Enter fullscreen mode Exit fullscreen mode

Example 3: Project Task Management

Let's take an advanced example: managing tasks in a project. You can create a Task class and use a list to manage these tasks. Tasks can have dependencies, due dates, and priorities.

public class ProjectTask
{
    public string Name { get; set; }
    public DateTime DueDate { get; set; }
    public bool IsCompleted { get; set; }

    public ProjectTask(string name, DateTime dueDate)
    {
        Name = name;
        DueDate = dueDate;
        IsCompleted = false;
    }
}

List<ProjectTask> projectTasks = new List<ProjectTask>
{
    new ProjectTask("Design Database", DateTime.Now.AddDays(7)),
    new ProjectTask("Develop API", DateTime.Now.AddDays(14)),
    new ProjectTask("Testing", DateTime.Now.AddDays(21))
};

// Mark a task as completed
projectTasks[1].IsCompleted = true;

// Add a new task
projectTasks.Add(new ProjectTask("Deploy to Production", DateTime.Now.AddDays(28)));

// Display all tasks and their statuses
foreach (var task in projectTasks)
{
    Console.WriteLine($"Task: {task.Name}, Due: {task.DueDate.ToShortDateString()}, Completed: {task.IsCompleted}");
}
Enter fullscreen mode Exit fullscreen mode

Assignments

To help reinforce your understanding of collections and lists, here are three assignments at different difficulty levels.

Easy Level Assignment: Game Scores List

Task: Create a list of integers representing scores in a game. Allow the user to input scores until they enter -1. Display the highest and lowest scores.

Steps:

  1. Create a List to Store Scores:

    • Define a list to store the scores that the user will enter.
    • Use List<int> scores = new List<int>();.
  2. Input Scores from User:

    • Use a loop to keep accepting scores from the user.
    • Stop taking input when the user enters -1.
   List<int> scores = new List<int>();
   Console.WriteLine("Enter scores one by one (-1 to stop):");

   int score;
   while (true)
   {
       Console.Write("Enter score: ");
       score = int.Parse(Console.ReadLine());

       if (score == -1) break;
       scores.Add(score);
   }
Enter fullscreen mode Exit fullscreen mode
  1. Check if the List has Scores:
    • Before proceeding, make sure there are scores in the list to avoid exceptions.
   if (scores.Count == 0)
   {
       Console.WriteLine("No scores entered.");
       return;
   }
Enter fullscreen mode Exit fullscreen mode
  1. Display Highest and Lowest Scores:
    • Use LINQ methods like Max() and Min() to get the highest and lowest scores.
   int highestScore = scores.Max();
   int lowestScore = scores.Min();

   Console.WriteLine($"Highest Score: {highestScore}");
   Console.WriteLine($"Lowest Score: {lowestScore}");
Enter fullscreen mode Exit fullscreen mode

Medium Level Assignment: Book Management System

Task: Create a Book class with properties Title and Author. Create a list of books and implement functionality to:

  • Add a new book.
  • Remove a book by title.
  • Search for a book by author.

Steps:

  1. Create the Book Class:
    • Define a class named Book with properties for Title and Author.
   public class Book
   {
       public string Title { get; set; }
       public string Author { get; set; }

       public Book(string title, string author)
       {
           Title = title;
           Author = author;
       }
   }
Enter fullscreen mode Exit fullscreen mode
  1. Create a List of Books:
    • Use List<Book> to store all the books.
   List<Book> books = new List<Book>();
Enter fullscreen mode Exit fullscreen mode
  1. Add a New Book:
    • Define a method to add a new book.
   void AddBook(string title, string author)
   {
       books.Add(new Book(title, author));
       Console.WriteLine("Book added successfully.");
   }

   // Example usage
   AddBook("The Great Gatsby", "F. Scott Fitzgerald");
Enter fullscreen mode Exit fullscreen mode
  1. Remove a Book by Title:
    • Define a method to remove a book by searching for its title.
   void RemoveBook(string title)
   {
       Book bookToRemove = books.FirstOrDefault(b => b.Title.Equals(title, StringComparison.OrdinalIgnoreCase));
       if (bookToRemove != null)
       {
           books.Remove(bookToRemove);
           Console.WriteLine("Book removed successfully.");
       }
       else
       {
           Console.WriteLine("Book not found.");
       }
   }

   // Example usage
   RemoveBook("The Great Gatsby");
Enter fullscreen mode Exit fullscreen mode
  1. Search for a Book by Author:
    • Define a method to search for books by the author.
   void SearchBooksByAuthor(string author)
   {
       var booksByAuthor = books.FindAll(b => b.Author.Equals(author, StringComparison.OrdinalIgnoreCase));
       if (booksByAuthor.Count > 0)
       {
           Console.WriteLine("Books by " + author + ":");
           foreach (var book in booksByAuthor)
           {
               Console.WriteLine($"- {book.Title}");
           }
       }
       else
       {
           Console.WriteLine("No books found by this author.");
       }
   }

   // Example usage
   SearchBooksByAuthor("F. Scott Fitzgerald");
Enter fullscreen mode Exit fullscreen mode

Difficult Level Assignment: Student Management System

Task: Create a Student class that includes properties like Name, Grade, and Subjects (which itself is a list of subjects). Implement functionality to:

  • Add new students.
  • Update a student's grade.
  • Add or remove subjects for a student.
  • Calculate the average grade of all students.

Steps:

  1. Create the Student Class:
    • Define a class Student with properties Name, Grade, and Subjects.
   public class Student
   {
       public string Name { get; set; }
       public double Grade { get; set; }
       public List<string> Subjects { get; set; }

       public Student(string name, double grade)
       {
           Name = name;
           Grade = grade;
           Subjects = new List<string>();
       }
   }
Enter fullscreen mode Exit fullscreen mode
  1. Create a List of Students:
    • Use List<Student> to store all the students.
   List<Student> students = new List<Student>();
Enter fullscreen mode Exit fullscreen mode
  1. Add New Students:
    • Define a method to add a new student.
   void AddStudent(string name, double grade)
   {
       students.Add(new Student(name, grade));
       Console.WriteLine("Student added successfully.");
   }

   // Example usage
   AddStudent("Alice", 85.5);
Enter fullscreen mode Exit fullscreen mode
  1. Update a Student's Grade:
    • Define a method to update the grade of a student by name.
   void UpdateStudentGrade(string name, double newGrade)
   {
       Student student = students.FirstOrDefault(s => s.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
       if (student != null)
       {
           student.Grade = newGrade;
           Console.WriteLine("Student grade updated successfully.");
       }
       else
       {
           Console.WriteLine("Student not found.");
       }
   }

   // Example usage
   UpdateStudentGrade("Alice", 90.0);
Enter fullscreen mode Exit fullscreen mode
  1. Add or Remove Subjects for a Student:
    • Define methods to add and remove subjects.
   void AddSubject(string studentName, string subject)
   {
       Student student = students.FirstOrDefault(s => s.Name.Equals(studentName, StringComparison.OrdinalIgnoreCase));
       if (student != null)
       {
           student.Subjects.Add(subject);
           Console.WriteLine("Subject added successfully.");
       }
       else
       {
           Console.WriteLine("Student not found.");
       }
   }

   void RemoveSubject(string studentName, string subject)
   {
       Student student = students.FirstOrDefault(s => s.Name.Equals(studentName, StringComparison.OrdinalIgnoreCase));
       if (student != null && student.Subjects.Contains(subject))
       {
           student.Subjects.Remove(subject);
           Console.WriteLine("Subject removed successfully.");
       }
       else
       {
           Console.WriteLine("Subject or student not found.");
       }
   }

   // Example usage
   AddSubject("Alice", "Math");
   RemoveSubject("Alice", "Math");
Enter fullscreen mode Exit fullscreen mode
  1. Calculate the Average Grade of All Students:
    • Define a method to calculate the average grade using LINQ.
   void CalculateAverageGrade()
   {
       if (students.Count == 0)
       {
           Console.WriteLine("No students available.");
           return;
       }

       double averageGrade = students.Average(s => s.Grade);
       Console.WriteLine($"Average Grade of all students: {averageGrade:F2}");
   }

   // Example usage
   CalculateAverageGrade();
Enter fullscreen mode Exit fullscreen mode

Summary

These assignments cover a range of complexity levels to help you strengthen your understanding of collections in C#:

  1. Easy: You worked with integers and used a list to keep track of scores.
  2. Medium: You managed a collection of custom objects (Book) with basic CRUD operations.
  3. Difficult: You built a more complex Student management system with nested lists and various functionalities.

Practicing these examples will improve your understanding of generic collections, type safety, and working with data in a structured way in C#.

Conclusion

The List class is a powerful tool in C# that you'll use often when dealing with collections of data. Unlike arrays, lists are dynamic, flexible, and provide type safety, making them easier to work with and less prone to errors. You can leverage the built-in methods to add, remove, and manage data efficiently.

.

Top comments (0)