在如何只能暴露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操作符允许根据需要创建项。这是一个使用它的好理由。
这个链接有一个简单的例子
这里还有更简单的例子
public static IEnumerable<int> testYieldb()
{
for(int i=0;i<3;i++) yield return 4;
}
注意yield return不会从方法返回。你甚至可以在收益率后面加上一个WriteLine
上面生成了一个4个整数的IEnumerable (4,4,4,4)
这里有一个WriteLine。将向列表中添加4,打印abc,然后向列表中添加4,然后完成方法,从而真正从方法中返回(一旦方法完成,就像没有返回的过程一样)。但它会有一个值,一个IEnumerable int列表,它会在补全时返回。
public static IEnumerable<int> testYieldb()
{
yield return 4;
console.WriteLine("abc");
yield return 4;
}
还要注意,当使用yield时,返回的结果与函数的类型不同。它是IEnumerable列表中的元素类型。
将yield与方法的返回类型一起使用IEnumerable。如果方法的返回类型是int或List<int>并且使用yield,那么它将不会被编译。你可以在没有yield的情况下使用IEnumerable方法返回类型,但似乎你不能在没有IEnumerable方法返回类型的情况下使用yield。
为了让它执行,你必须用特殊的方式调用它。
static void Main(string[] args)
{
testA();
Console.Write("try again. the above won't execute any of the function!\n");
foreach (var x in testA()) { }
Console.ReadLine();
}
// static List<int> testA()
static IEnumerable<int> testA()
{
Console.WriteLine("asdfa");
yield return 1;
Console.WriteLine("asdf");
}