Update all objects in a collection using LINQ

C#.NetLinqForeach

C# Problem Overview


Is there a way to do the following using LINQ?

foreach (var c in collection)
{
    c.PropertyToSet = value;
}

To clarify, I want to iterate through each object in a collection and then update a property on each object.

My use case is I have a bunch of comments on a blog post, and I want to iterate through each comment on a blog post and set the datetime on the blog post to be +10 hours. I could do it in SQL, but I want to keep it in the business layer.

C# Solutions


Solution 1 - C#

While you can use a ForEach extension method, if you want to use just the framework you can do

collection.Select(c => {c.PropertyToSet = value; return c;}).ToList();

The ToList is needed in order to evaluate the select immediately due to lazy evaluation.

Solution 2 - C#

collection.ToList().ForEach(c => c.PropertyToSet = value);

Solution 3 - C#

I am doing this

Collection.All(c => { c.needsChange = value; return true; });

Solution 4 - C#

I actually found an extension method that will do what I want nicely

public static IEnumerable<T> ForEach<T>(
    this IEnumerable<T> source,
    Action<T> act)
{
    foreach (T element in source) act(element);
    return source;
}

Solution 5 - C#

Use:

ListOfStuff.Where(w => w.Thing == value).ToList().ForEach(f => f.OtherThing = vauleForNewOtherThing);

I am not sure if this is overusing LINQ or not, but it has worked for me when wanting to update a specific items in the list for a specific condition.

Solution 6 - C#

Although you specifically asked for a LINQ solution and this question is quite old I post a non-LINQ-solution. This is because LINQ (= language integrated query) is meant to be used for queries on collections. All LINQ-methods don’t modify the underlying collection, they just return a new one (or more precise an iterator to a new collection). Thus whatever you do e.g. with a Select doesn’t effect the underlying collection, you simply get a new one.

Of course you could do it with a ForEach (which isn't LINQ, by the way, but an extension on List<T>). But this literally uses foreach anyway, but with a lambda-expression. Apart from this every LINQ method internally iterates your collection e.g. by using foreach or for, however it simply hides it from the client. I don’t consider this any more readable nor maintainable (think of edit your code while debugging a method containing lambda-expressions).

Having said this shouldn't use LINQ to modify items in your collection. A better way is the solution you already provided in your question. With a classic loop you can easily iterate your collection and update its items. In fact all those solutions relying on List.ForEach are nothing different, but far harder to read from my perspective.

So you shouldn't use LINQ in those cases where you want to update the elements of your collection.

Solution 7 - C#

There is no built-in extension method to do this. Although defining one is fairly straight forward. At the bottom of the post is a method I defined called Iterate. It can be used like so

collection.Iterate(c => { c.PropertyToSet = value;} );

Iterate Source

public static void Iterate<T>(this IEnumerable<T> enumerable, Action<T> callback)
{
    if (enumerable == null)
    {
        throw new ArgumentNullException("enumerable");
    }

    IterateHelper(enumerable, (x, i) => callback(x));
}

public static void Iterate<T>(this IEnumerable<T> enumerable, Action<T,int> callback)
{
    if (enumerable == null)
    {
        throw new ArgumentNullException("enumerable");
    }

    IterateHelper(enumerable, callback);
}

private static void IterateHelper<T>(this IEnumerable<T> enumerable, Action<T,int> callback)
{
    int count = 0;
    foreach (var cur in enumerable)
    {
        callback(cur, count);
        count++;
    }
}

Solution 8 - C#

I've tried a few variations on this, and I keep going back to this guy's solution.

http://www.hookedonlinq.com/UpdateOperator.ashx

Again, this is somebody else's solution. But I've compiled the code into a small library, and use it fairly regularly.

I'm going to paste his code here, for the off chance that his site(blog) ceases to exist at some point in the future. (There's nothing worse than seeing a post that says "Here is the exact answer you need", Click, and Dead URL.)

    public static class UpdateExtensions {

    public delegate void Func<TArg0>(TArg0 element);

    /// <summary>
    /// Executes an Update statement block on all elements in an IEnumerable<T> sequence.
    /// </summary>
    /// <typeparam name="TSource">The source element type.</typeparam>
    /// <param name="source">The source sequence.</param>
    /// <param name="update">The update statement to execute for each element.</param>
    /// <returns>The numer of records affected.</returns>
    public static int Update<TSource>(this IEnumerable<TSource> source, Func<TSource> update)
    {
        if (source == null) throw new ArgumentNullException("source");
        if (update == null) throw new ArgumentNullException("update");
        if (typeof(TSource).IsValueType)
            throw new NotSupportedException("value type elements are not supported by update.");

        int count = 0;
        foreach (TSource element in source)
        {
            update(element);
            count++;
        }
        return count;
    }
}



int count = drawingObjects
        .Where(d => d.IsSelected && d.Color == Colors.Blue)
        .Update(e => { e.Color = Color.Red; e.Selected = false; } );

Solution 9 - C#

No, LINQ doesn't support a manner of mass updating. The only shorter way would be to use a ForEach extension method - https://stackoverflow.com/questions/101265/why-is-there-not-a-foreach-extension-method-on-the-ienumerable-interface#101303

Solution 10 - C#

My 2 pennies:-

 collection.Count(v => (v.PropertyToUpdate = newValue) == null);

Solution 11 - C#

You can use LINQ to convert your collection to an array and then invoke Array.ForEach():

Array.ForEach(MyCollection.ToArray(), item=>item.DoSomeStuff());

Obviously this will not work with collections of structs or inbuilt types like integers or strings.

Solution 12 - C#

I wrote some extension methods to help me out with that.

namespace System.Linq
{
    /// <summary>
    /// Class to hold extension methods to Linq.
    /// </summary>
    public static class LinqExtensions
    {
        /// <summary>
        /// Changes all elements of IEnumerable by the change function
        /// </summary>
        /// <param name="enumerable">The enumerable where you want to change stuff</param>
        /// <param name="change">The way you want to change the stuff</param>
        /// <returns>An IEnumerable with all changes applied</returns>
        public static IEnumerable<T> Change<T>(this IEnumerable<T> enumerable, Func<T, T> change  )
        {
            ArgumentCheck.IsNullorWhiteSpace(enumerable, "enumerable");
            ArgumentCheck.IsNullorWhiteSpace(change, "change");

            foreach (var item in enumerable)
            {
                yield return change(item);
            }
        }

        /// <summary>
        /// Changes all elements of IEnumerable by the change function, that fullfill the where function
        /// </summary>
        /// <param name="enumerable">The enumerable where you want to change stuff</param>
        /// <param name="change">The way you want to change the stuff</param>
        /// <param name="where">The function to check where changes should be made</param>
        /// <returns>
        /// An IEnumerable with all changes applied
        /// </returns>
        public static IEnumerable<T> ChangeWhere<T>(this IEnumerable<T> enumerable, 
                                                    Func<T, T> change,
                                                    Func<T, bool> @where)
        {
            ArgumentCheck.IsNullorWhiteSpace(enumerable, "enumerable");
            ArgumentCheck.IsNullorWhiteSpace(change, "change");
            ArgumentCheck.IsNullorWhiteSpace(@where, "where");

            foreach (var item in enumerable)
            {
                if (@where(item))
                {
                    yield return change(item);
                }
                else
                {
                    yield return item;
                }
            }
        }

        /// <summary>
        /// Changes all elements of IEnumerable by the change function that do not fullfill the except function
        /// </summary>
        /// <param name="enumerable">The enumerable where you want to change stuff</param>
        /// <param name="change">The way you want to change the stuff</param>
        /// <param name="where">The function to check where changes should not be made</param>
        /// <returns>
        /// An IEnumerable with all changes applied
        /// </returns>
        public static IEnumerable<T> ChangeExcept<T>(this IEnumerable<T> enumerable,
                                                     Func<T, T> change,
                                                     Func<T, bool> @where)
        {
            ArgumentCheck.IsNullorWhiteSpace(enumerable, "enumerable");
            ArgumentCheck.IsNullorWhiteSpace(change, "change");
            ArgumentCheck.IsNullorWhiteSpace(@where, "where");

            foreach (var item in enumerable)
            {
                if (!@where(item))
                {
                    yield return change(item);
                }
                else
                {
                    yield return item;
                }
            }
        }

        /// <summary>
        /// Update all elements of IEnumerable by the update function (only works with reference types)
        /// </summary>
        /// <param name="enumerable">The enumerable where you want to change stuff</param>
        /// <param name="update">The way you want to change the stuff</param>
        /// <returns>
        /// The same enumerable you passed in
        /// </returns>
        public static IEnumerable<T> Update<T>(this IEnumerable<T> enumerable,
                                               Action<T> update) where T : class
        {
            ArgumentCheck.IsNullorWhiteSpace(enumerable, "enumerable");
            ArgumentCheck.IsNullorWhiteSpace(update, "update");
            foreach (var item in enumerable)
            {
                update(item);
            }
            return enumerable;
        }

        /// <summary>
        /// Update all elements of IEnumerable by the update function (only works with reference types)
        /// where the where function returns true
        /// </summary>
        /// <param name="enumerable">The enumerable where you want to change stuff</param>
        /// <param name="update">The way you want to change the stuff</param>
        /// <param name="where">The function to check where updates should be made</param>
        /// <returns>
        /// The same enumerable you passed in
        /// </returns>
        public static IEnumerable<T> UpdateWhere<T>(this IEnumerable<T> enumerable,
                                               Action<T> update, Func<T, bool> where) where T : class
        {
            ArgumentCheck.IsNullorWhiteSpace(enumerable, "enumerable");
            ArgumentCheck.IsNullorWhiteSpace(update, "update");
            foreach (var item in enumerable)
            {
                if (where(item))
                {
                    update(item);
                }
            }
            return enumerable;
        }

        /// <summary>
        /// Update all elements of IEnumerable by the update function (only works with reference types)
        /// Except the elements from the where function
        /// </summary>
        /// <param name="enumerable">The enumerable where you want to change stuff</param>
        /// <param name="update">The way you want to change the stuff</param>
        /// <param name="where">The function to check where changes should not be made</param>
        /// <returns>
        /// The same enumerable you passed in
        /// </returns>
        public static IEnumerable<T> UpdateExcept<T>(this IEnumerable<T> enumerable,
                                               Action<T> update, Func<T, bool> where) where T : class
        {
            ArgumentCheck.IsNullorWhiteSpace(enumerable, "enumerable");
            ArgumentCheck.IsNullorWhiteSpace(update, "update");

            foreach (var item in enumerable)
            {
                if (!where(item))
                {
                    update(item);
                }
            }
            return enumerable;
        }
    }
}

I am using it like this:

        List<int> exampleList = new List<int>()
            {
                1, 2 , 3
            };

        //2 , 3 , 4
        var updated1 = exampleList.Change(x => x + 1);

        //10, 2, 3
        var updated2 = exampleList
            .ChangeWhere(   changeItem => changeItem * 10,          // change you want to make
                            conditionItem => conditionItem < 2);    // where you want to make the change

        //1, 0, 0
        var updated3 = exampleList
            .ChangeExcept(changeItem => 0,                          //Change elements to 0
                          conditionItem => conditionItem == 1);     //everywhere but where element is 1

For reference the argument check:

/// <summary>
/// Class for doing argument checks
/// </summary>
public static class ArgumentCheck
{
    

    /// <summary>
    /// Checks if a value is string or any other object if it is string
    /// it checks for nullorwhitespace otherwhise it checks for null only
    /// </summary>
    /// <typeparam name="T">Type of the item you want to check</typeparam>
    /// <param name="item">The item you want to check</param>
    /// <param name="nameOfTheArgument">Name of the argument</param>
    public static void IsNullorWhiteSpace<T>(T item, string nameOfTheArgument = "")
    {

        Type type = typeof(T);
        if (type == typeof(string) ||
            type == typeof(String))
        {
            if (string.IsNullOrWhiteSpace(item as string))
            {
                throw new ArgumentException(nameOfTheArgument + " is null or Whitespace");
            }
        }
        else
        {
            if (item == null)
            {
                throw new ArgumentException(nameOfTheArgument + " is null");
            }
        }

    }
}

Solution 13 - C#

You can use Magiq, a batch operation framework for LINQ.

Solution 14 - C#

Here is the extension method I use...

    /// <summary>
    /// Executes an Update statement block on all elements in an  IEnumerable of T
    /// sequence.
    /// </summary>
    /// <typeparam name="TSource">The source element type.</typeparam>
    /// <param name="source">The source sequence.</param>
    /// <param name="action">The action method to execute for each element.</param>
    /// <returns>The number of records affected.</returns>
    public static int Update<TSource>(this IEnumerable<TSource> source, Func<TSource> action)
    {
        if (source == null) throw new ArgumentNullException("source");
        if (action == null) throw new ArgumentNullException("action");
        if (typeof (TSource).IsValueType)
            throw new NotSupportedException("value type elements are not supported by update.");

        var count = 0;
        foreach (var element in source)
        {
            action(element);
            count++;
        }
        return count;
    }

Solution 15 - C#

Some people consider this is a comment, but for me is an answer, because the right way to do something wrong is not do it. So, the answer for this question is in the question itself.

> DO NOT USE LINQ to modify data. Use a loop.

Solution 16 - C#

I assume you want to change values inside a query so you could write a function for it

void DoStuff()
{
    Func<string, Foo, bool> test = (y, x) => { x.Bar = y; return true; };
    List<Foo> mylist = new List<Foo>();
    var v = from x in mylist
            where test("value", x)
            select x;
}

class Foo
{
    string Bar { get; set; }
}

But not shure if this is what you mean.

Solution 17 - C#

Quoting Adi Lester's answer (https://stackoverflow.com/a/5755487/8917485)

I quite like this answer, but this answer has a bug. It just changes values in a new created list. It must be changed to two lines to read the real changed list.

var aList = collection.ToList();
aList.ForEach(c => c.PropertyToSet = value);

Solution 18 - C#

Suppose we have data like below,

var items = new List<string>({"123", "456", "789"});
// Like 123 value get updated to 123ABC ..

and if we want to modify the list and replace the existing values of the list to modified values, then first create a new empty list, then loop through data list by invoking modifying method on each list item,

var modifiedItemsList = new List<string>();

items.ForEach(i => {
  var modifiedValue = ModifyingMethod(i);
  modifiedItemsList.Add(items.AsEnumerable().Where(w => w == i).Select(x => modifiedValue).ToList().FirstOrDefault()?.ToString()) 
});
// assign back the modified list
items = modifiedItemsList;

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionlomaxxView Question on Stackoverflow
Solution 1 - C#Cameron MacFarlandView Answer on Stackoverflow
Solution 2 - C#Ε Г И І И ОView Answer on Stackoverflow
Solution 3 - C#RahulView Answer on Stackoverflow
Solution 4 - C#lomaxxView Answer on Stackoverflow
Solution 5 - C#HennishView Answer on Stackoverflow
Solution 6 - C#MakePeaceGreatAgainView Answer on Stackoverflow
Solution 7 - C#JaredParView Answer on Stackoverflow
Solution 8 - C#granadaCoderView Answer on Stackoverflow
Solution 9 - C#Aaron PowellView Answer on Stackoverflow
Solution 10 - C#AnthonyWJonesView Answer on Stackoverflow
Solution 11 - C#Tamas CzinegeView Answer on Stackoverflow
Solution 12 - C#PartTimeIndieView Answer on Stackoverflow
Solution 13 - C#ivosView Answer on Stackoverflow
Solution 14 - C#Bill ForneyView Answer on Stackoverflow
Solution 15 - C#Leandro BardelliView Answer on Stackoverflow
Solution 16 - C#StormenetView Answer on Stackoverflow
Solution 17 - C#江明哲View Answer on Stackoverflow
Solution 18 - C#Vishwa GView Answer on Stackoverflow