Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using LINQ to change values in collection

Tags:

linq

I think I'm not undertanding LINQ well. I want to do:

foreach (MyObjetc myObject in myObjectCollection)
{
    myObjet.MyProperty = newValue
}

Just change all values for a property in all elements of my collection.

Using LINQ wouldn't be this way?

myObjectCollection.Select(myObject => myObject.MyProperty = newValue)

It doesn't work. The property value is not changed. Why?

Edit:

Sorry, guys. Certainly, foreach is the right way. But,in my case, I must repeat the foreach in many collections, and I didn't want to repeat the loop. So, finally, I have found an 'inermediate' solution, the 'foreach' method, just similar to the 'Select':

myObjectCollection.ForEach(myObject => myObject.MyProperty = newValue)

Anyway may be it's not as clear as the more simple:

foreach (MyObjetc myObject in myObjectCollection) myObjet.MyProperty = newValue;
like image 544
Kaikus Avatar asked Nov 14 '13 00:11

Kaikus


1 Answers

First off, this is not a good idea. See below for arguments against it.

It doesn't work. The property value is not changed. Why?

It doesn't work because Select() doesn't actually iterate through the collection until you enumerate it's results, and it requires an expression that evaluates to a value.

If you make your expression return a value, and add something that will fully evaluate the query, such as ToList(), to the end, then it will "work", ie:

myObjectCollection.Select(myObject => { myObject.MyProperty = newValue; return myObject;}).ToList();

That being said, ToList() has some disadvantages - mainly, it's doing a lot of extra work (to create a List<T>) that's not needed, which adds a large cost. Avoiding it would require enumerating the collection:

foreach(var obj in myObjectCollection.Select(myObject => { myObject.MyProperty = newValue; return myObject; })) 
{ }

Again, I wouldn't recommend this. At this point, the Select option is far uglier, more typing, etc. It's also a violation of the expectations involved with LINQ - LINQ is about querying, which suggests there shouldn't be side effects when using LINQ, and the entire purpose here is to create side effects.

But then, at this point, you're better off (with less typing) doing it the "clear" way:

foreach (var obj in myObjectCollection)
{
     obj.MyProperty = newValue;
}

This is shorter, very clear in its intent, and very clean.

Note that you can add a ForEach<T> extension method which performs an action on each object, but I would still recommend avoiding that. Eric Lippert wrote a great blog post about the subject that is worth a read: "foreach" vs "ForEach".

like image 83
Reed Copsey Avatar answered Oct 20 '22 11:10

Reed Copsey