Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change the property of objects in a List using LINQ

Tags:

c#

list

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();
like image 349
Vahid Avatar asked Apr 30 '14 23:04

Vahid


2 Answers

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.

https://ericlippert.com/2009/05/18/foreach-vs-foreach/

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.

like image 148
Eric J. Avatar answered Oct 15 '22 08:10

Eric J.


foreach(Beam beam in Beams.Where(x => x.Width > 40))
{
     beam.IsJoist = true;
} 
like image 40
Jacob Seleznev Avatar answered Oct 15 '22 08:10

Jacob Seleznev