[c#] LINQ: Select an object and change some properties without creating a new object

I want to change some properties of a LINQ query result object without creating a new object and manually setting every property. Is this possible?

Example:

var list = from something in someList
           select x // but change one property

This question is related to c# linq

The answer is


User u = UserCollection.Single(u => u.Id == 1);
u.FirstName = "Bob"

If you just want to update the property on all elements then

someList.All(x => { x.SomeProp = "foo"; return true; })

If you want to update items with a Where clause, using a .Where(...) will truncate your results if you do:

mylist = mylist.Where(n => n.Id == ID).Select(n => { n.Property = ""; return n; }).ToList();

You can do updates to specific item(s) in the list like so:

mylist = mylist.Select(n => { if (n.Id == ID) { n.Property = ""; } return n; }).ToList();

Always return item even if you don't make any changes. This way it will be kept in the list.


var item = (from something in someList
       select x).firstordefault();

Would get the item, and then you could do item.prop1=5; to change the specific property.

Or are you wanting to get a list of items from the db and have it change the property prop1 on each item in that returned list to a specified value? If so you could do this (I'm doing it in VB because I know it better):

dim list = from something in someList select x
for each item in list
    item.prop1=5
next

(list will contain all the items returned with your changes)


There shouldn't be any LINQ magic keeping you from doing this. Don't use projection though that'll return an anonymous type.

User u = UserCollection.FirstOrDefault(u => u.Id == 1);
u.FirstName = "Bob"

That will modify the real object, as well as:

foreach (User u in UserCollection.Where(u => u.Id > 10)
{
    u.Property = SomeValue;
}

Since I didn´t find the answer here which I consider the best solution, here my way:

Using "Select" to modify data is possible, but just with a trick. Anyway, "Select" is not made for that. It just executes the modification when used with "ToList", because Linq doesn´t execute before the data is being needed. Anyway, the best solution is using "foreach". In the following code, you can see:

    class Person
    {
        public int Age;
    }

    class Program
    {
        private static void Main(string[] args)
        {
            var persons = new List<Person>(new[] {new Person {Age = 20}, new Person {Age = 22}});
            PrintPersons(persons);

            //this doesn't work:
            persons.Select(p =>
            {
                p.Age++;
                return p;
            });
            PrintPersons(persons);

            //with "ToList" it works
            persons.Select(p =>
            {
                p.Age++;
                return p;
            }).ToList();
            PrintPersons(persons);

            //This is the best solution
            persons.ForEach(p =>
            {
                p.Age++;
            });
            PrintPersons(persons);
            Console.ReadLine();
        }

        private static void PrintPersons(List<Person> persons)
        {
            Console.WriteLine("================");
            foreach (var person in persons)
            {
                Console.WriteLine("Age: {0}", person.Age);
            ;
            }
        }
    }

Before "foreach", you can also make a linq selection...


We often run into this where we want to include a the index value and first and last indicators in a list without creating a new object. This allows you to know the position of the item in your list, enumeration, etc. without having to modify the existing class and then knowing whether you're at the first item in the list or the last.

foreach (Item item in this.Items
    .Select((x, i) => {
    x.ListIndex = i;
    x.IsFirst = i == 0;
    x.IsLast = i == this.Items.Count-1;
    return x;
}))

You can simply extend any class by using:

public abstract class IteratorExtender {
    public int ListIndex { get; set; }
    public bool IsFirst { get; set; } 
    public bool IsLast { get; set; } 
}

public class Item : IteratorExtender {}

It is not possible with the standard query operators - it is Language Integrated Query, not Language Integrated Update. But you could hide your update in extension methods.

public static class UpdateExtension
{
    public static IEnumerable<Car> ChangeColorTo(
       this IEnumerable<Car> cars, Color color)
    {
       foreach (Car car in cars)
       {
          car.Color = color;
          yield return car;
       }
    }
}

Now you can use it as follows.

cars.Where(car => car.Color == Color.Blue).ChangeColorTo(Color.Red);


I prefer this one. It can be combined with other linq commands.

from item in list
let xyz = item.PropertyToChange = calcValue()
select item