简体   繁体   English

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

[英]Console output by extension method that returns IEnumerable<T>

I'm using Visual Studio 2013.我正在使用 Visual Studio 2013。

When the following code is executed, ForEach2 outputs to the console, but there is no output by ForEach .执行以下代码时, ForEach2输出到控制台,但ForEach没有输出。 I was surprised that I thought they would have the same result.我很惊讶我认为他们会得到相同的结果。 Is this a specification, or is something wrong in our environment?这是规范,还是我们的环境有问题? What are the specifications, if any?如果有,规格是什么?

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

When I set a breakpoint, it doesn't seem to get into ForEach in the first place.当我设置断点时,它似乎并没有首先进入ForEach I tried to suppress optimization with [MethodImpl (MethodImplOptions.NoOptimization)] but the result was the same.我试图用[MethodImpl (MethodImplOptions.NoOptimization)]抑制优化,但结果是一样的。

The yield statement in the ForEach method means the method will not be executed until you iterate over the items in the IEnumerable<T> returned by ForEach . ForEach方法中的yield语句意味着在您迭代ForEach返回的IEnumerable<T>的项目之前,不会执行该方法。 You can see this is true by putting a breakpoint on the action(item);您可以通过在action(item);上放置断点来看到这是真的action(item); line in your code - the breakpoint is not hit.代码中的行 - 未命中断点。

If you want the code to execute you will need to add a foreach for the values returned from ForEach .如果您希望代码执行,您需要为从ForEach返回的值添加一个foreach For example:例如:

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

The new line will cause the ForEach to execute and yield each result.新行将导致ForEach执行并产生每个结果。 This will cause the action(item) to execute and print the result to the console.这将导致action(item)执行并将结果打印到控制台。

The remarks in the yield docs page tell you that you need to use foreach or LINQ to consume the results of a yield statement. yield docs 页面中的注释告诉您需要使用foreachLINQ来使用yield语句的结果。

You've defined a generator method, but since you haven't enumerated the results, nothing happens.您已经定义了一个生成器方法,但是由于您还没有枚举结果,所以什么也没有发生。 Which do you want, the callback or the enumerator?你想要哪个,回调还是枚举器?

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM