c# - Why do changes made in foreach to a Linq grouping select get ignored unless I add ToList()? -


i have following method.

public ienumerable<item> changevalueienumerable()     {         var items = new list<item>(){             new item("item1", 1),             new item("item2", 1),             new item("item3", 2),             new item("item4", 2),             new item("item5", 3)         };          var groupeditems = items.groupby(i => i.value)             .select(x => new item(x.first().name, x.key));          foreach (var item in groupeditems)         {             item.calculatedvalue = item.name + item.value;         }          return groupeditems;     } 

into groupeditems collection calculatedvalues null. if add tolist() select sentence after groupby calculatedvalues has values. example:

 var groupeditems = items.groupby(i => i.value)             .select(x => new item(x.first().name, x.key)).tolist(); 

so, question is. why this? want know reason this, solution me add tolist()

update: defition of item class following

 public class item {     public string name { get; set; }     public int value { get; set; }      public string calculatedvalue { get; set; }      public item(string name, int value)     {         this.name = name;         this.value = value;     } } 

var groupeditems = items.groupby(i => i.value)     .select(x => new item(x.first().name, x.key)); 

here, groupeditems doesn't hold items. ienumerable<t> returned select represents computation - precise, represents result of mapping items new set of items applying function x => new item(x.first().name, x.key).

each time iterate on groupeditems, function applied , new set of items created.

var groupeditems = items.groupby(i => i.value)     .select(x =>      {         console.writeline("creating new item");         return new item(x.first().name, x.key));     }  foreach(var item in groupeditems); foreach(var item in groupeditems); 

this code, example, print "creating new item" twice each item in items.

in code, you're setting calculatedvalue of ephemeral item. when foreach loop done, items gone.

by calling tolist, you're turning "computation" actual collection of items.

instead of calling tolist, alternatively create another computation represents new set of items calculatedvalue property set. functional way.

func<item, item> withcalculatedvalue =     item => {         item.calculatedvalue = item.name + item.value;         return item;     };  return items.groupby(i => i.value)         .select(x => new item(x.first().name, x.key))         .select(withcalculatedvalue); 

or use object initializers

return items.groupby(i => i.value)         .select(x => new item(x.first().name, x.key) { calculatedvalue = x.first().name + x.key }); 

if want little bit more research on topic of objects hold computations, google term "monad", prepared confused.


Comments

Popular posts from this blog

javascript - AngularJS custom datepicker directive -

javascript - jQuery date picker - Disable dates after the selection from the first date picker -