System.Linq.Enumerable+d__3a`1[System.String] error in LINQ foreach loop

I have a list that I am trying to populate from another list in which I want to combine some data and eliminate some.

In the original list the data looks like this:

 Id     Text      Description

  1      Apple     Red Delicious
  1      Apple     Green
  1      Apple     Granny 
  2      Tomato    Roma
  2      Tomato    Cherry   

I want to condense this information in the second list to look like this:

  Id    Text     Description
  1     Apple    Red Delicious, Green, Granny
  2     Tomato   Roma, Cherry 

My class object is declared like this:

 [Serializable]
 public class Food
 {
     public int Id { get;set; }
     public string Text { get;set; }
     public string Description { get;set; } 
 }

So I want to loop through the old list and this is how I'm trying to do it in the code:

var ids = oldList.Select(i => i.Id).Distinct(); //get distinct list of ids (e.g. 1,2)
List<Food> newList = ids.Select(i => new Food(){
   Id = i,
   Text = oldList.Where(o => o.Id == i).Select(o => o.Text).Take(1).ToString(),
   Description = string.Join(",", oldList.Where(o => o.Id == i).Select(o => o.Description).ToString())
}).ToList();

Right now I'm getting the System.Linq.Enumerable+d__3a`1[System.String] error because of .Take(), but if I change it just .ToString(), I get a slightly different error but from the same source System.linq.Enumerable, if I do FirstOrDefault() same thing, .Distinct() same thing.

I think I understand that the problem is that for Text and Description its returning IEnumerable for Text and Description so I'm not getting the actual values that I want and I'm not sure I understand how to correctly convert it .ToList(). What is the correct way to access these values?

Jon Skeet
people
quotationmark

You're calling ToString() on the result of Take and Select - and that's not going to do anything nice. It's not clear why you're calling ToString explicitly in Description, and for Text you really want FirstOrDefault or First instead, as you just want the first result:

List<Food> newList = ids.Select(i => new Food {
   Id = i,
   Text = oldList.Where(o => o.Id == i).Select(o => o.Text).FirstOrDefault(),
   Description = string.Join(",", oldList.Where(o => o.Id == i)
                                         .Select(o => o.Description))
}).ToList();

Basically, calling ToString() on a sequence (IEnumerable<T>) is almost never appropriate.

people

See more on this question at Stackoverflow