当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《使用LINQ更新集合中的所有对象》经验,为你挑选了7个好方法。

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

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

为了澄清,我想迭代集合中的每个对象,然后更新每个对象的属性.

我的用例是我在博客文章中有一堆评论,我想在博客文章中迭代每个评论,并将博客帖子上的日期时间设置为+10小时.我可以在SQL中完成它,但我想将它保留在业务层中.



1> Cameron MacF..:

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

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

ToList是必要的,以评估立即选择由于懒惰的评估.


恕我直言,这远比简单的foreach循环更具表现力.ToList()令人困惑,因为它不会用于强制评估的任何内容,否则将被延迟.该预测也令人困惑,因为它没有用于其预期目的; 相反,它用于迭代集合的元素并允许访问属性以便可以更新它.在我看来,唯一的问题是foreach循环是否可以使用Parallel.ForEach从并行性中受益,但这是一个不同的问题.
**这个答案是最糟糕的做法。永远不要这样做。**
如果集合是一个`ObservableCollection`,那么更改项目而不是创建新列表可能很有用.
@desaivv是的,这是一种语法滥用,所以Resharper警告你这件事.
我赞成这个,因为它是一个非常好的解决方案...我喜欢扩展方法的唯一原因是它使得更清楚地了解到底发生了什么...但是你的解决方案仍然很好
有人可以解释为什么这是最高的投票答案?为什么这比使用ForEach更好?
@KonradMorawski你正在对IQueryable进行选择而不是IEnumerable,所以很可能是LINQ to SQL.这仅适用于LINQ to对象.
请参阅所有其他注释,以了解为什么这是一个坏主意的原因。您绝对不要使用select来执行副作用。选择的目的是选择一个值,而不是为每个循环模拟一个。
我很震惊,这是第一答案,并且有很多票。此代码绝对是一场噩梦。当您只可以使用ForEach时为什么要使用select?甚至for循环的2行语法也更易于编写,并且更能体现代码的作用。为了上帝的爱,请不要在您的代码中这样做!
@ Pan.student地狱没有.说实话,我不确定我是否会使用这种技术.
此代码在对集合进行操作时会对其进行突变。“选择”实际上应该是不变的,并避免类似的副作用。ToList也导致分配另一个集合。从本质上讲,此代码乍一看并没有做什么。任何熟悉LINQ扫描的人都不会期望对该集合进行修改。
考虑https://blogs.msdn.microsoft.com/ericlippert/2009/05/18/foreach-vs-foreach/
我尝试了但是我继续遇到编译器错误:`带有语句体的lambda表达式无法转换为表达式树`.当我把它提取到`Func`时,再次没问题了.为什么?
@ShiftN'Tab:Lambda表达式通常包含一个语句,例如`x => x.Id`.但是,它们可以有多个语句.在这种情况下,您需要在多个语句周围使用大括号.此外,如果需要从多语句lambda返回一个值,则使用`return`语句.上面的例子包括一个多语句lambda:`c => {c.PropertyToSet = value; return c;}`.它有2个语句,为了清楚起见,你通常会在不同的行上写:`c.PropertyToSet = value;`和`return c;`它非常像一个C#2.0匿名方法.

2> Ε Г И І И О..:
collection.ToList().ForEach(c => c.PropertyToSet = value);


@SanthoshKumar:使用`collection.ToList().ForEach(c => {c.Property1ToSet = value1; c.Property2ToSet = value2;});`
这比Cameron MacFarland更新列表的答案更有优势,而不是创建新列表.
哇,这个答案真的没用.创建一个新集合只是为了能够使用循环
我该怎么做才能更新多个房产?
我使用VB.NET,这对我不起作用:(

3> Rahul..:

我这样做

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


这种方法肯定有效,但它违反了`All()`扩展方法的意图,当其他人读取代码时会导致混淆.
绝对更喜欢这个不必要地调用ToList(),即使它对使用All()的内容有点误导.

4> lomaxx..:

我实际上找到了一个扩展方法,可以很好地完成我想要的操作

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


很好:) Lomaxx,也许添加一个例子,所以窥视可以在'动作'中看到它(繁荣的tish!).
如果您确实想避免`foreach`循环(无论出于何种原因),这是唯一有用的方法。

5> Hennish..:

使用:

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

我不确定这是否过度使用LINQ,但是当想要更新列表中特定条件的特定项时,它对我有用.



6> JaredPar..:

没有内置的扩展方法来执行此操作.虽然定义一个是相当直接的.在帖子的底部是我定义的一个名为Iterate的方法.它可以像这样使用

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

迭代源

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

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

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

    IterateHelper(enumerable, callback);
}

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


这非常接近我想要的,但是有点..涉及。我发布的博客文章具有类似的实现方式,但代码行较少。
@ Cameron,IterateHelper有两个用途。1)单一实现和2)允许在调用时与使用时引发ArgumentNullException。C#迭代器被延迟执行,使助手能够防止在迭代过程中引发异常的奇怪行为。
@JaredPar:除非您没有使用迭代器。没有收益声明。

7> granadaCoder..:

我已经尝试了一些变化,我会继续回到这个人的解决方案.

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

再次,这是别人的解决方案.但我已经将代码编译成一个小型库,并且经常使用它.

我将在这里粘贴他的代码,因为他的网站(博客)将来某个时候不再存在.(没有什么比看到帖子上写着"这是你需要的确切答案",点击和死网更糟糕了.)

    public static class UpdateExtensions {

    public delegate void Func(TArg0 element);

    /// 
    /// Executes an Update statement block on all elements in an IEnumerable sequence.
    /// 
    /// The source element type.
    /// The source sequence.
    /// The update statement to execute for each element.
    /// The numer of records affected.
    public static int Update(this IEnumerable source, Func 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; } );

推荐阅读
和谐啄木鸟
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有