返回IEnumerable< T>与IDisposable实例的yield

本文关键字:IDisposable 实例 yield IEnumerable 返回 | 更新日期: 2023-09-27 18:11:44

我发现了一件有趣的事情。c#。NET 4.0。我有一个代表IDisposable接口的类。在上面提到的类中,我有一个函数,它返回IEnumerable和yield return。在调用时,控件跳过该函数。不要介入。例子:

class Program
{
    static void Main(string[] args)
    {
        using (DispClass d = new DispClass())
        {
            d.Get2();
            d.Get1();
        }
    }
}
public class DispClass: IDisposable
{
    public DispClass()
    {
        Console.WriteLine("Constructor");
    }
    public void Dispose()
    {
        Console.WriteLine("Dispose");
    }
    public int Get1()
    {
        Console.WriteLine("Getting one");
        return 1;
    }
    public IEnumerable<int> Get2()
    {
        Console.WriteLine("Getting 1");
        yield return 1;
        Console.WriteLine("Getting 2");
        yield return 2;
    }
}

输出:"构造函数"一"处理"

"得到1","得到2"在哪里?没有yield return,返回一个本地列表,我可以看到这些…

请解释!

返回IEnumerable< T>与IDisposable实例的yield

这是预期的行为和设计。当您使用yield时,实际发生的情况是Get2方法返回由编译器自动实现的类型的实例。该类型实现IEnumerable<T>接口。在枚举对象被枚举之前,迭代器方法中的代码实际上不会被调用。由于您没有枚举Get2调用的结果,因此您的代码永远不会被调用。要强制它,使用ToArray()ToList():

 d.Get2().ToList();

方法Get2()中的代码只有在迭代该方法返回的IEnumerable时才会执行。由于本例中的IEnumerable包含两个元素,因此它将两次输入此代码—在第一次迭代中,它将执行前两行并在"yield return 1;在下一次迭代中,它将进入函数并在"Console"行开始执行。WriteLine(" get 2");"并从那里继续。

因此,如果您没有遍历这两个项目,即在获得值1之后,您没有移动到IEnumerable中的下一个项目,那么该函数将不会再次输入。试着把你的程序改成下面的代码,以便更好地理解。

    static void Main(string[] args)
    {
        using (DispClass d = new DispClass())
        {
            var lst = d.Get2();
            //d.Get1();
            foreach (var a in lst)
            {
                break;
            }
        }
        Console.ReadKey();
    }