我正在执行C#练习来创建一个操作,该操作接受一个集合,对该集合中的每个对象执行一个功能,然后返回修改后的对象的集合。
我的代码当前如下:
public static IEnumerable<U> Accumulate<T, U>(this IEnumerable<T> collection, Func<T, U> func)
{
IEnumerable<U> output = Enumerable.Empty<U>();
foreach (T item in collection)
{
output.Append(func(item));
}
return output;
}
这只是返回一个空集合,我不知道为什么。
在另一个线程中看到这种方法后,我尝试在foreach中创建项目的副本,如下所示:
foreach (T item in collection)
{
U copy = func(item);
output.Append(copy);
}
但这并不能解决任何问题。
我做了一些研究,但实际上找不到任何示例完全符合我在此尝试做的事情。我读了一些有关闭包的内容,但由于我是C#的新手,所以无法真正理解。
答案 0 :(得分:10)
要回答您的实际问题:不起作用的原因是因为
output.Append(func(item));
不更改output
-而是返回一个新序列,该序列附加到func(item)
的{{1}}上。因此,当您最终返回output
时,您只是在返回原始的空序列。
您可以通过以下简单的更改使您的工作正常:
output
但是,这不是一种有效的方法-使用yield
会更好,方法如下:
output = output.Append(func(item));
尽管请注意,它更简单地表示为:
public static IEnumerable<U> Accumulate<T, U>(this IEnumerable<T> collection, Func<T, U> func)
{
foreach (T item in collection)
{
yield return func(item);
}
}
但是了解如何使用public static IEnumerable<U> Accumulate<T, U>(this IEnumerable<T> collection, Func<T, U> func)
{
return collection.Select(item => func(item));
}
来执行此操作很有用,这样您就可以为更复杂的类似Linq的问题编写解决方案。
答案 1 :(得分:2)
通常,当我想实现这种行为时,我会使用C#迭代器。 当您要处理某种类型的数据的迭代时,它们非常有用,并且在每次迭代时,返回一个附加到结果集合中的值。
看看文档:{{3}}