Search code examples
c#linqcsvstringbuilder

Looping through List values in C# and saving them to a CSV


I'm doing something wrong here, and perhaps you could help.

What I'm trying to achieve is:

  1. Read the CSV file (only one line, based on the ID) and map the property values to an object.
  2. Update the object's values.
  3. Write the updated values back to the CSV file.

I can accomplish the first and the second step.

For instance, here is how I define the object that maps to CSV fields:

    public string Property1 { get; set; } = string.Empty;
    public string Property2 { get; set; } = string.Empty; 

    public static CSVData ReadFromCSV(string line)
    {
        string[] values = line.Split(';');
        CSVData csvValues = new CSVData();

        csvValues.Property1 = values[0];
        csvValues.Property2 = values[1];

        return csvValues;
    }

Then, I call the ReadFromCSVMethod like this:

id = "123456";

var csvLine = File.ReadAllLines("C:\\test.csv")
             .Skip(1)
             .Select(line => CSVData.ReadFromCSV(line))
             .Where(i => i.ID == id)
             .ToList();

// update values
csvLine[0].Property1 = "foo";
csvLine[1].Property2 = "bar;

I can see the updated values in csvLine when I look at them.

Finally, I try to loop through the list (csvList), grab the values and put a semicolon between these values:

var sb = new StringBuilder();

foreach (var item in csvList)
{
   sb.Append(item);
}

But this is where I face an issue. When I try to see what's inside the StringBuilder, all I get is the object name (CSVProcessor.CSVData), not the property values:

var result = sb.ToString();

Why this is happening?

The idea is to form a string (new line) and then save it to a CSV.


Solution

  • This happens because the StringBuilder uses the ToString method of your object to convert it to a string. The default behavior of ToString (inherited from object) is to return the type name.

    You must create a semicolon-separated string, e.g. with:

    sb.Append(item.Property1).Append(';').Append(item.Property2);
    

    You could also override ToString in the CSVData class:

    public override string ToString()
    {
        return Property1 + ";" + Property2;
    }
    

    And then use

    Append(item);