在通用列表中,有没有办法以声明/ LINQ方式将一个属性复制到另一个属性?

时间:2010-07-30 02:38:47

标签: c# linq generics

我有一个有两个属性的类,比如说

public class Book {
public string TitleSource { get; set; }
public string TitleTarget { get; set; }
}

我有一个IList<Book> TitleTarget为空,对于列表中的每个项目,我需要将TitleSource属性复制到TitleTarget属性。我可以通过一个循环来做到这一点,当然,但似乎有一个LINQ或很好的声明方式来做到这一点。有吗?

5 个答案:

答案 0 :(得分:4)

Linq被设计为一种消费方式。如果你看一下关于为什么没有IEnumerable.ForEach(...)扩展的网络讨论,你会发现Linq设计者有目的地避免了Linq to Object场景,其中方法被设计为改变对象值。

也就是说,您可以通过“选择”值而不使用结果来作弊。但是,这会产生被扔掉的物品。因此,foreach循环效率更高。

为真正想要除了foreach之外的其他人

进行编辑

另一个不会产生新列表的“作弊”将是使用一种方法来完成它自己的工作,如Aggregate,All或Any。

// Return true so All will go through the whole list.
books.All(book => { book.TitleTarget = book.TitleSource; return true; });

答案 1 :(得分:1)

这不是LINQ,但是有:

books.Where(book => book.TitleTarget == null).ToList()
     .ForEach(book => book.TitleTarget = book.TitleSource);

主要观点是ToList方法调用:没有ForEach扩展方法(我不认为?)但直接在List<T>上有一个方法。编写自己的ForEach扩展方法也不难。

至于这是否比简单的foreach循环好,我不太确定。我个人会选择foreach循环,因为它使意图(你想要修改集合)更清晰。

答案 2 :(得分:1)

@John Fisher是正确的,没有IEnumerable.ForEach

List<T>上有一个ForEach。所以你可以做到以下几点:

List<Book> books = GetBooks();
books.ForEach(b => b.TitleTarget = b.TitleSource);

如果你想要一个IEnumerable.ForEach,那么很容易创建一个:

public static class LinqExtensions
{
    public static void ForEach<TSource>(this IEnumerable<TSource> source, Action<TSource> action)
    {
        foreach (var item in source)
        {
            action(item);
        }
    }
}

然后,您可以使用以下代码段在整个集合中执行操作:

IList<Book> books = GetBooks();
books.ForEach(b => b.TitleTarget = b.TitleSource);

答案 3 :(得分:1)

如果您可以使用.NET 4.0,并且您使用的是线程安全的集合,那么您可以使用新的并行ForEach构造:

using System.Threading.Tasks;

...

Parallel.ForEach(
    books.Where(book => book.TitleTarget == null),
    book => book.TitleTarget = book.TitleSource);

这将排队要在线程池上运行的任务 - 一个任务将执行集合中每本书的赋值委托。

对于大型数据集,这可能会提高性能,但是考虑到管理线程同步的开销,对于较小的集合实际上可能会更慢。

答案 4 :(得分:0)

books.Select(b => b.TitleTarget = b.TitleSource);

这不会创建任何“新项目”,只是您不会枚举的查询。这对我来说似乎没什么大不了的。