DEV Community

mohamed Tayel
mohamed Tayel

Posted on

Dynamic Data Handling in C#: Resizing Collections with List<T>

"Learn how to manage dynamic collections in C# with List<T>. This guide covers resizing collections, adding and removing items, and using lists for flexible data handling. Perfect for mastering dynamic data in C#! #CSharp #ProgrammingTips"

In this article, we’ll build upon the Excel-driven console application created earlier to demonstrate how to replace the fixed-size Array with the flexible List<T> for managing country data. We’ll cover why lists are ideal when you don’t know the size of your data set in advance and show you how to dynamically add, search, and manipulate data using List<T>.


What You'll Learn

  1. The key differences between Array and List<T>.
  2. How to dynamically add, remove, and insert items in a List<T>.
  3. How to iterate through lists, count their elements, and search efficiently.
  4. How to use List<T> to handle dynamically sized data sets, such as country data from an Excel file.

Why Switch to List<T>?

In the previous demo, we used a fixed-size array to store country data. However, arrays have limitations:

  • You must know their size when you instantiate them.
  • Arrays cannot grow or shrink dynamically.

By switching to List<T>, we gain the ability to:

  • Dynamically add countries without knowing the total count beforehand.
  • Perform operations like inserting, searching, and removing items more flexibly.

Step 1: Update the ExcelReaderWriter Class

In this step, we’ll modify the ReadFirstNCountries method to dynamically read all countries into a List<Country>.

Updated Method to Read All Countries

public List<Country> ReadAllCountries()
{
    var countries = new List<Country>();

    using (var package = new ExcelPackage(new FileInfo(_filePath)))
    {
        var worksheet = package.Workbook.Worksheets["Countries"];
        int row = 2; // Data starts from the second row

        while (worksheet.Cells[row, 1].Value != null)
        {
            var name = worksheet.Cells[row, 1].Value?.ToString();
            var code = worksheet.Cells[row, 2].Value?.ToString();
            var region = worksheet.Cells[row, 3].Value?.ToString();
            var population = int.Parse(worksheet.Cells[row, 4].Value?.ToString() ?? "0");

            countries.Add(new Country(name, code, region, population));
            row++;
        }
    }

    return countries;
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Update the Main Method

We’ll modify the Main method to read all countries into a List<Country> and demonstrate additional operations like searching and inserting.

Updated Main Method

static void Main(string[] args)
{
    string filePath = "Countries.xlsx";
    var excelHandler = new ExcelReaderWriter(filePath);

    // Step 1: Create Excel with Sample Data
    Console.WriteLine("Creating sample data...");
    excelHandler.CreateSampleData();
    Console.WriteLine($"Sample data created at {filePath}");

    // Step 2: Read All Countries from Excel
    Console.WriteLine("Reading all countries from Excel...");
    var countries = excelHandler.ReadAllCountries();

    // Step 3: Display the Countries
    Console.WriteLine("\nAll Countries:");
    foreach (var country in countries)
    {
        Console.WriteLine($"{country.Name.PadRight(20)} {PopulationFormatter.FormatPopulation(country.Population).PadLeft(15)}");
    }

    // Step 4: Insert a New Country
    Console.WriteLine("\nInserting Lilliput...");
    var lilliput = new Country("Lilliput", "LL", "Fictional", 2000000);
    int lilliputIndex = countries.FindIndex(c => c.Population < lilliput.Population);
    countries.Insert(lilliputIndex, lilliput);

    // Step 5: Display After Insertion
    Console.WriteLine("\nCountries After Insertion:");
    foreach (var country in countries)
    {
        Console.WriteLine($"{country.Name.PadRight(20)} {PopulationFormatter.FormatPopulation(country.Population).PadLeft(15)}");
    }

    // Step 6: Remove the Inserted Country
    Console.WriteLine("\nRemoving Lilliput...");
    countries.RemoveAt(lilliputIndex);

    // Step 7: Display After Removal
    Console.WriteLine("\nCountries After Removal:");
    foreach (var country in countries)
    {
        Console.WriteLine($"{country.Name.PadRight(20)} {PopulationFormatter.FormatPopulation(country.Population).PadLeft(15)}");
    }

    // Step 8: Count the Countries
    Console.WriteLine($"\nTotal Countries: {countries.Count}");
}
Enter fullscreen mode Exit fullscreen mode

Key Features of List<T> Demonstrated

  1. Dynamic Sizing

    • Lists start empty and grow dynamically using the Add method.
  2. Inserting with List<T>.Insert()

    • The Insert method allows placing an item at a specific index.
    • In the example, Lilliput was inserted in the correct position based on population.
  3. Searching with List<T>.FindIndex()

    • The FindIndex method locates the index of the first country whose population is less than Lilliput’s.
  4. Removing with List<T>.RemoveAt()

    • The RemoveAt method deletes the country at a specific index.
  5. Counting Elements with List<T>.Count

    • Unlike arrays, lists use the Count property to get the number of elements.

Expected Output

Here’s what you’ll see in the console:

Creating sample data...
Sample data created at Countries.xlsx
Reading all countries from Excel...

All Countries:
China               1,412,600,000
India               1,366,417,754
United States         331,883,986
Indonesia             273,523,621
Pakistan              220,892,331
...

Inserting Lilliput...

Countries After Insertion:
China               1,412,600,000
India               1,366,417,754
...
Lilliput                  2,000,000
Latvia                     1,900,000
...

Removing Lilliput...

Countries After Removal:
China               1,412,600,000
India               1,366,417,754
...
Latvia                     1,900,000
...

Total Countries: 217
Enter fullscreen mode Exit fullscreen mode

Why Use List<T> Over Arrays?

  1. Flexibility: No need to specify size upfront.
  2. Ease of Operations:
    • Adding, removing, and inserting items are straightforward.
  3. Integration: The same foreach loop syntax works for both arrays and lists.

Performance Considerations

  • Inserting or removing items in large lists can cause performance issues, as elements may need to be shifted in memory.
  • For frequent insertions/removals, consider using other data structures like LinkedList<T>.

Conclusion

Switching from arrays to List<T> adds flexibility and functionality to your applications. With List<T>, you can dynamically manage data, search efficiently, and perform advanced operations like inserting and removing items. This makes it a powerful tool for handling real-world data scenarios like our Excel-driven country demo.

Top comments (0)