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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/398871/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 01:56:21  来源:igfitidea点击:

Update all objects in a collection using LINQ

c#.netlinqforeach

提问by lomaxx

Is there a way to do the following using LINQ?

有没有办法使用 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.

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

采纳答案by Cameron MacFarland

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

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

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

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

ToList是必要的,以评估立即到期选择偷懒的评价

回答by JaredPar

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

没有内置的扩展方法可以做到这一点。虽然定义一个是相当简单的。在帖子的底部是我定义的一个名为 Iterate 的方法。它可以像这样使用

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

回答by Aaron Powell

No, LINQ doesn't support a manner of mass updating. The only shorterway would be to use a ForEachextension method - Why there is no ForEach extension method on IEnumerable?

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

回答by Stormenet

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.

但不确定这是否是您的意思。

回答by AnthonyWJones

My 2 pennies:-

我的 2 便士:-

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

回答by lomaxx

I actually found an extension methodthat 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;
}

回答by Tamas Czinege

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

您可以使用 LINQ 将您的集合转换为数组,然后调用 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.

显然,这不适用于结构集合或内置类型(如整数或字符串)。

回答by ivos

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

您可以使用Magiq,一个用于 LINQ 的批处理操作框架。

回答by Bill Forney

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

回答by granadaCoder

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

我已经尝试了一些变化,我一直回到这个人的解决方案。

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

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.)

我将把他的代码贴在这里,以防他的网站(博客)在未来的某个时候不复存在。(没有什么比看到“这是您需要的确切答案”、点击和死 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; } );