Vahid Vahid - 2 months ago 14
C# Question

Change the property of objects in a List using LINQ

I have list of

Beam
objects. How can I change the
IsJoist
property of the beams when the
Width
property is greater than 40 using LINQ?

class Beam
{
public double Width { get; set; }
public bool IsJoist { get; set; }
}

var bm1 = new Beam { Width = 40 };
var bm2 = new Beam { Width = 50 };
var bm3 = new Beam { Width = 30 };
var bm4 = new Beam { Width = 60 };

var Beams = new List<Beam> { bm1, bm2, bm3, bm4 };


Here is what I have done but I'm only getting a List. I want the new list to be the same as the original one except that the IsJoist property for some beams will be set to true.

var result = Beams
.Where(x => x.Width > 40)
.Select(x => x.IsJoist = true)
.ToList();


I was able to implement this as below. Is it ok since LINQ is meant for queries?

var result = Beams
.Where(x => x.Width > 40)
.Select(x =>
{
x.IsJoist = true;
return x;
})
.ToList();

Answer

If your solution must be completely Linq, you could do

Beams.Where(x => x.Width > 40).ToList().ForEach(b => b.IsJoist = true);

However, that is not an ideal way to implement this (@Jacob's answer is a better one). Check out Eric Lippert's blog entry on the topic. The most important lines for me are

The first reason is that doing so violates the functional programming principles that all the other sequence operators are based upon. Clearly the sole purpose of a call to this method is to cause side effects. The purpose of an expression is to compute a value, not to cause a side effect. The purpose of a statement is to cause a side effect.

http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx

Note that ToList() is called because List<T> provides a ForEach() method, while Linq in general does not offer such an extension method for the reasons Eric Lippert cites in that blog entry.

UPDATE

Your code both updates entities in the original list (changes IsJoist to true for certain conditions) and returns references to the objects that were updated. If that is what you intended, the code functions. However, Linq is designed with a functional paradigm in mind. Introducing side effects within the context of a Linq expression violates the functional programming principal behind the extension methods.