使用LINQ更新集合中的所有对象

有没有办法使用LINQ执行以下操作?

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

为了澄清,我想遍历集合中的每个对象,然后更新每个对象的属性。

我的用例是我在博客文章上有一堆评论,我想遍历博客文章上的每条评论,并将博客文章的date时间设置为+10小时。 我可以在SQL中完成,但是我想保留在业务层中。

虽然您可以使用ForEach扩展方法,但如果您只想使用框架,则可以执行此操作

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

由于懒惰的评估ToList是需要立即评估select的。

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

我正在这样做

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

我实际上find了一个扩展方法 ,将做我想要的很好

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

使用:

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

我不确定这是否过度使用LINQ,但它已经为我工作,当想要更新列表中的特定条件的特定条件。

没有内置的扩展方法来做到这一点。 虽然定义一个相当简单。 在post的底部是我定义的一个叫做迭代的方法。 它可以像这样使用

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

迭代源

 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++; } } 

我已经尝试了一些这方面的变化,我不断回到这家伙的解决scheme。

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

再次,这是别人的解决scheme。 但是我把代码编译成一个小型的库,并且定期使用它。

我要在这里粘贴他的代码,以免他的网站(博客)在将来某个时候不再存在。 (没有什么比看到一个post说“这是你需要的确切答案”,点击和死链接更糟糕。)

  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; } ); 

我的两个便士: –

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

我写了一些扩展方法来帮助我解决这个问题。

 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; } } } 

我正在像这样使用它:

  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 

参考参数检查:

 /// <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"); } } } } 

不,LINQ不支持大规模更新的方式。 唯一更简单的方法是使用ForEach扩展方法 – 为什么IEnumerable上没有ForEach扩展方法?

这是我使用的扩展方法…

  /// <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; } 

您可以使用Magiq ,这是LINQ的批处理操作框架。

我假设你想改变查询内的值,所以你可以写一个函数

 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; } } 

但是,如果这就是你的意思,那么不能保证。

您可以使用LINQ将您的集合转换为数组,然后调用Array.ForEach():

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

显然这不适用于结构集合或内置types,如整数或string。