是否有一种方法来做以下使用LINQ?

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

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

我的用例是我在一篇博客文章上有一堆评论,我想迭代一篇博客文章上的每一条评论,并将博客文章上的datetime设置为+10小时。我可以用SQL来做,但我想把它保留在业务层。


当前回答

有些人认为这是一种评论,但对我来说是一种回答,因为做错事的正确方法是不去做。所以,这个问题的答案就在问题本身。

不要使用LINQ来修改数据。使用循环。

其他回答

这是我使用的扩展方法…

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

虽然你特别要求一个LINQ解决方案,这个问题很老了,但我发布了一个非LINQ解决方案。这是因为LINQ (= 语言集成查询)用于对集合进行查询。所有linq方法都不修改底层集合,它们只是返回一个新的集合(或者更准确地说是一个指向新集合的迭代器)。因此,无论你做什么,例如使用Select都不会影响底层集合,你只是获得一个新的集合。

当然,您可以使用ForEach(顺便说一下,这不是LINQ,而是List<T>上的扩展)。但是这里实际上使用了foreach,但是使用了lambda表达式。除此之外,每个LINQ方法都在内部迭代你的集合,例如通过使用foreach或for,然而它只是对客户端隐藏它。我不认为这更具可读性或可维护性(考虑在调试包含lambda-expressions的方法时编辑代码)。

说到这里,不应该使用LINQ来修改集合中的项目。更好的方法是你在问题中已经提供的解决方案。使用经典循环,您可以轻松迭代集合并更新其中的项目。事实上,所有这些解决方案都依赖于List。每一个都没有什么不同,但从我的角度来看很难理解。

所以你不应该在那些你想要更新集合元素的情况下使用LINQ。

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

没有内置的扩展方法可以做到这一点。尽管定义一个是相当简单的。在这篇文章的底部是我定义的一个叫做Iterate的方法。它可以这样使用

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

引用Adi Lester的回答(https://stackoverflow.com/a/5755487/8917485)

我很喜欢这个答案,但这个答案有一个错误。它只是改变一个新创建的列表中的值。它必须更改为两行才能读取真正的更改列表。

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