返回 IEnumerable <T>的扩展方法的控制台输出



我正在使用Visual Studio 2013。

执行以下代码时,ForEach2输出到控制台,但ForEach没有输出。我很惊讶我以为他们会有同样的结果。这是一个规范,还是我们的环境中出了问题?如果有的话,规格是什么?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var array = new[] { 1, 2, 3 };
Console.WriteLine("ForEach:");
array.ForEach(a => Console.WriteLine(a));
Console.WriteLine("ForEach2:");
array.ForEach2(a => Console.WriteLine(a));
Console.ReadKey();
}
}
static class Extension
{
public static IEnumerable<T> ForEach<T>(this IEnumerable<T> target, Action<T> action)
{
foreach (var item in target)
{
action(item);
yield return item;
}
}
public static void ForEach2<T>(this IEnumerable<T> target, Action<T> action)
{
foreach (var item in target)
{
action(item);
}
}
}
}

当我设置断点时,它似乎一开始就没有进入ForEach。我试图用[MethodImpl (MethodImplOptions.NoOptimization)]抑制优化,但结果是一样的。

ForEach方法中的yield语句意味着在循环访问ForEach返回的IEnumerable<T>中的项之前不会执行该方法。通过在代码action(item);行上放置断点,可以看到这是真的 - 不会命中断点。

如果您希望代码执行,则需要为从ForEach返回的值添加一个foreach。例如:

static void Main(string[] args)
{
var array = new[] { 1, 2, 3 };
Console.WriteLine("ForEach:");
array.ForEach(a => Console.WriteLine(a));
// add this line
foreach (var b in array.ForEach(a => Console.WriteLine(a))) { }
Console.WriteLine("ForEach2:");
array.ForEach2(a => Console.WriteLine(a));
Console.ReadKey();
}

新行将导致ForEach执行并生成每个结果。这将导致action(item)执行并将结果打印到控制台。

收益文档页面中的备注告诉您,您需要使用foreachLINQ来使用yield语句的结果。

你已定义生成器方法,但由于尚未枚举结果,因此没有任何反应。你想要哪个,回调还是枚举器?

public static IEnumerable<T> ForEach<T>(this IEnumerable<T> target)
{
foreach (var item in target)
{
yield return item;
}
}
Console.WriteLine("ForEach:");
foreach (var item in array.ForEach())
Console.WriteLine(item);

最新更新