在如何只能暴露IList<>的一个片段问题中,其中一个答案有以下代码片段:
IEnumerable<object> FilteredList()
{
foreach(object item in FullList)
{
if(IsItemInPartialList(item))
yield return item;
}
}
yield关键字在这里做什么?我在一些地方看到过它,还有一个问题,但我还没搞清楚它到底是干什么的。我习惯于从一个线程屈服于另一个线程的意义上考虑屈服,但这在这里似乎无关紧要。
乍一看,yield return是一个。net糖返回一个IEnumerable。
如果没有yield,集合中的所有项都是一次性创建的:
class SomeData
{
public SomeData() { }
static public IEnumerable<SomeData> CreateSomeDatas()
{
return new List<SomeData> {
new SomeData(),
new SomeData(),
new SomeData()
};
}
}
同样的代码使用yield,它逐项返回:
class SomeData
{
public SomeData() { }
static public IEnumerable<SomeData> CreateSomeDatas()
{
yield return new SomeData();
yield return new SomeData();
yield return new SomeData();
}
}
使用yield的优点是,如果使用数据的函数只需要集合的第一个项,则不会创建其余的项。
yield操作符允许根据需要创建项。这是一个使用它的好理由。
Yield return与枚举器一起使用。在yield语句的每次调用中,控制权都返回给调用方,但它确保被调用方的状态得到维护。因此,当调用方枚举下一个元素时,它将在yield语句之后立即在被调用方方法from语句中继续执行。
让我们通过一个例子来理解这一点。在这个例子中,对应于每一行,我已经提到了执行流的顺序。
static void Main(string[] args)
{
foreach (int fib in Fibs(6))//1, 5
{
Console.WriteLine(fib + " ");//4, 10
}
}
static IEnumerable<int> Fibs(int fibCount)
{
for (int i = 0, prevFib = 0, currFib = 1; i < fibCount; i++)//2
{
yield return prevFib;//3, 9
int newFib = prevFib + currFib;//6
prevFib = currFib;//7
currFib = newFib;//8
}
}
此外,还为每个枚举维护状态。假设,我对Fibs()方法有另一个调用,那么它的状态将被重置。
乍一看,yield return是一个。net糖返回一个IEnumerable。
如果没有yield,集合中的所有项都是一次性创建的:
class SomeData
{
public SomeData() { }
static public IEnumerable<SomeData> CreateSomeDatas()
{
return new List<SomeData> {
new SomeData(),
new SomeData(),
new SomeData()
};
}
}
同样的代码使用yield,它逐项返回:
class SomeData
{
public SomeData() { }
static public IEnumerable<SomeData> CreateSomeDatas()
{
yield return new SomeData();
yield return new SomeData();
yield return new SomeData();
}
}
使用yield的优点是,如果使用数据的函数只需要集合的第一个项,则不会创建其余的项。
yield操作符允许根据需要创建项。这是一个使用它的好理由。