2017-03-24 133 views
1

FirstMethod被定义为迭代器方法。假定SecondMethod被定义为调用FirstMethod,但直接返回结果而不是foreach以及其项目。如果ThirdMethod遍历SecondMethod的结果,是整个链处理为迭代,还是实现这样的必须我yield里面的SecondMethod返回迭代器方法

例如

IEnumerable<string> FirstMethod() 
{ 
    yield return "one"; 
    yield return "two"; 
    yield return "three"; 
} 

IEnumerable<string> SecondMethod() 
{ 
    return FirstMethod(); 
} 

IEnumerable<string> ThirdMethod() 
{ 
    foreach (string item in SecondMethod()) 
    { 
    yield return item; 
    } 
} 

void Main() 
{ 
    foreach (string item in ThirdMethod()) 
    { 
    Console.WriteLine(item); 
    } 
} 

我意识到我仍然会得到所有的项目在这个例子中显示。然而,我担心的是保留迭代器的“懒惰”评估直到Main

+0

你可以在你的例子中加入一些'Console.WriteLine()'调用并自己回答。 –

回答

2

是的,它会保持懒惰。您将返回一个IEnumerable<T>,直到枚举结果才会实现结果。

您的代码的行为方式与您要省略SecondMethod并从ThirdMethod调用FirstMethod完全相同。

您可以通过删除日志报表内FirstMethod

IEnumerable<string> FirstMethod() 
{ 
    Console.WriteLine("Returning one"); 
    yield return "one"; 
    Console.WriteLine("Returning two"); 
    yield return "two"; 
    Console.WriteLine("Returning three"); 
    yield return "three"; 
} 

实际测试这个现在,你的调试器,把内SecondMethod断点。请注意,直到我们开始迭代SecondMethod()之前,没有任何内容被打印。以下是输出结果:

 
Returning one 
one 
Returning two 
two 
Returning three 
three 
1

为了理解它是如何工作的,可以简单地放置断点并对其进行调试。
另一种方法是添加一些调试输出点:

IEnumerable<string> FirstMethod() 
{ 
    Console.WriteLine("FirstMethod start."); 
    Console.WriteLine("FirstMethod: one"); 
    yield return "one"; 
    Console.WriteLine("FirstMethod: two"); 
    yield return "two"; 
    Console.WriteLine("FirstMethod: three"); 
    yield return "three"; 
    Console.WriteLine("FirstMethod end."); 
} 

IEnumerable<string> SecondMethod() 
{ 
    Console.WriteLine("SecondMethod start."); 
    return FirstMethod(); 
} 

IEnumerable<string> ThirdMethod() 
{ 
    Console.WriteLine("ThirdMethod start."); 
    foreach (string item in SecondMethod()) 
    { 
    Console.WriteLine("ThirdMethod: " + item); 
    yield return item; 
    } 
    Console.WriteLine("ThirdMethod end."); 
} 

void Main() 
{ 
    foreach (string item in ThirdMethod()) 
    { 
    Console.WriteLine("Main: " + item); 
    } 
} 

该代码产生成以下调用顺序:

ThirdMethod start. 
SecondMethod start. 
FirstMethod start. 
FirstMethod: one 
ThirdMethod: one 
Main: one 
FirstMethod: two 
ThirdMethod: two 
Main: two 
FirstMethod: three 
ThirdMethod: three 
Main: three 
FirstMethod end. 
ThirdMethod end. 

如果我们从Main删除foreach,然后我们得到空的输出。

所以,是的,“懒惰”的评价被保留,即SecondMethod只是返回IEnumerable,并且在Main中调用之后正在枚举值。

这就是LINQ究竟是如何保持这种行为,同时链接LINQ方法,只有当你调用.ToArray()列举,.ToList()等,或使用foreach