我试图了解使用Yield来枚举集合。我写了这个基本代码:
static void Main(string[] args)
{
Iterate iterate = new Iterate();
foreach (int i in iterate.EnumerateList())
{
Console.Write("{0}", i);
}
Console.ReadLine();
}
class Iterate
{
public IEnumerable<int> EnumerateList()
{
List<int> lstNumbers = new List<int>();
lstNumbers.Add(1);
lstNumbers.Add(2);
lstNumbers.Add(3);
lstNumbers.Add(4);
lstNumbers.Add(5);
foreach (int i in lstNumbers)
{
yield return i;
}
}
}
(1)如果我只使用return i
代替yield return i
怎么办?
(2)使用Yield有什么好处,何时更喜欢使用它?
已编辑**
在上面的代码中,我认为使用foreach
两次是一种开销。首先是main function
,第二个是EnumerateList
方法。
答案 0 :(得分:8)
使用yield return i
使此方法成为iterator。它将从整个循环中创建一个IEnumerable<int>
值序列。
如果您使用return i
,则只返回一个int
值。在您的情况下,这会导致编译器错误,因为您的方法的返回类型是IEnumerable<int>
,而不是int
。
在这个具体的例子中,我个人只返回lstNumbers
而不是使用迭代器。但是,您可以在没有列表的情况下重写此内容,如:
public IEnumerable<int> EnumerateList()
{
yield return 1;
yield return 2;
yield return 3;
yield return 4;
yield return 5;
}
甚至:
public IEnumerable<int> EnumerateList()
{
for (int i=1;i<=5;++i)
yield return i;
}
当你创建一个你想要像集合一样的课时,这非常方便。手动为自定义类型实现IEnumerable<T>
通常需要创建自定义类等。在迭代器之前,这需要大量代码,如old sample for implementing a custom collection in C#所示。
答案 1 :(得分:2)
正如Reed所说,使用yield
可以实现迭代器。迭代器的主要优点是它允许延迟评估。即除非需要,否则它不必实现整个结果。
从BCL考虑Directory.GetFiles
。它返回string[]
。即它必须获取所有文件并在返回之前将名称放在数组中。相比之下,Directory.EnumerateFiles
会返回IEnumerable<string>
。即调用者负责处理结果集。这意味着调用者可以在任何时候选择不再枚举集合。
答案 2 :(得分:1)
yield
关键字将使编译器将函数转换为枚举器对象。
yield return
语句不会简单地退出函数并返回一个值,它会使代码保持一个状态,以便在从枚举器请求下一个值时可以恢复该代码。
答案 3 :(得分:1)
你不能只返回我,因为我是一个int而不是IEnumerable。它甚至不会编译。您可以返回lstNumbers,因为它实现了IEnumerable的接口。
我更喜欢yield return,因为编译器将处理构建可枚举的内容而不必首先构建列表。所以对我来说,如果我有一些已经在实现接口的东西,那么我返回,如果我必须构建它而不是使用它,那么我产生返回。