1.写法有2种:
yield return <expression>和yield break
yield用于在迭代中返回一个值,并将值带入下一次迭代中。yield break则意味着停止迭代。纯粹的文字描述,一千个人有一千个说法,还是用代码更容易说清楚。
2.官方示例(略带修改):
private void button1_Click(object sender, EventArgs e) { string s = string.Empty; foreach (int i in List.Power(2,8)) { s += i.ToString() + ","; } MessageBox.Show(s); } public class List { //using System.Collections; public static IEnumerable Power(int number, int exponent) { int counter = 0; int result = 1; while (counter++ < exponent) { result = result * number; yield return result; } } }
运行示例,发现power方法中的while代码部分,每循环执行一次,即输出一个值,并将这个值带入下一次循环,而power函数并没有每次被调用。
为了验证,我们修改下官方示例代码,来看看我们的判断是否有误:
private void button1_Click(object sender, EventArgs e) { string s = string.Empty; foreach (int i in List.Power()) { s += i.ToString() + ","; } MessageBox.Show(s); } public static IEnumerable Power() { int counter = 0; int result = 1; int number = 2, exponent = 8; while (counter++ < exponent) { result = result * number; yield return result; } }
运行结果与官方示例相同,说明.net framework每次只把yield部分所在的部分代码进行了迭代返回处理。
3.官方的另一个示例为用yield作为属性(输出方式略有修改)。
private void button2_Click(object sender, EventArgs e) { var theGalaxies = new Galaxies(); string ps = string.Empty; foreach (Galaxy theGalaxy in theGalaxies.NextGalaxy) { ps += (theGalaxy.Name + " " + theGalaxy.MegaLightYears.ToString() + " >> "); } MessageBox.Show(ps); } public System.Collections.Generic.IEnumerable<Galaxy> NextGalaxy { get { yield return new Galaxy { Name = "Tadpole", MegaLightYears = 400 }; yield return new Galaxy { Name = "Pinwheel", MegaLightYears = 25 }; yield return new Galaxy { Name = "Milky Way", MegaLightYears = 0 }; yield return new Galaxy { Name = "Andromeda", MegaLightYears = 3 }; } }
输出结果:
从这个例子可以看出yield其实就是临时中断执行,输出后继续执行而已。
可以修改下这个例子,看效果如何:
public class Galaxies { List<Galaxy> ls = new List<Galaxy>(); public System.Collections.Generic.IEnumerable<Galaxy> NextGalaxy { get { yield return new Galaxy { Name = "Tadpole", MegaLightYears = 400 }; yield return new Galaxy { Name = "Pinwheel", MegaLightYears = 25 }; yield return new Galaxy { Name = "Milky Way", MegaLightYears = 0 }; yield return new Galaxy { Name = "Andromeda", MegaLightYears = 3 }; } } public System.Collections.Generic.IEnumerable<Galaxy> NextGalaxy1 { get { ls.Add(new Galaxy { Name = "Tadpole", MegaLightYears = 400 }); ls.Add(new Galaxy { Name = "Pinwheel", MegaLightYears = 25 }); ls.Add(new Galaxy { Name = "Milky Way", MegaLightYears = 0 }); ls.Add(new Galaxy { Name = "Andromeda", MegaLightYears = 3 }); int i = -1; while (i++ < ls.Count - 1) { yield return ls[i]; } } } }
调用NextGalaxy1后,结果与官方示例结果相同,还可以进一步修改NextGalaxy1,使其更容易别理解:
public System.Collections.Generic.IEnumerable<Galaxy> NextGalaxy1 { get { ls.Add(new Galaxy { Name = "Tadpole", MegaLightYears = 400 }); ls.Add(new Galaxy { Name = "Pinwheel", MegaLightYears = 25 }); ls.Add(new Galaxy { Name = "Milky Way", MegaLightYears = 0 }); ls.Add(new Galaxy { Name = "Andromeda", MegaLightYears = 3 }); int i = 0; while (i < ls.Count) { yield return ls[i]; i++; } } }
这样看来就很容易理解其含义了,更进一步说就是一边给你输出结果,一边继续给你执行代码,一举两得!
如果想中断执行,则直接用yield break即可。
代码如下:
public System.Collections.Generic.IEnumerable<Galaxy> NextGalaxy1 { get { ls.Add(new Galaxy { Name = "Tadpole", MegaLightYears = 400 }); ls.Add(new Galaxy { Name = "Pinwheel", MegaLightYears = 25 }); ls.Add(new Galaxy { Name = "Milky Way", MegaLightYears = 0 }); ls.Add(new Galaxy { Name = "Andromeda", MegaLightYears = 3 }); int i = -1; while (i++ < ls.Count - 1) { yield return ls[i]; if (ls[i].MegaLightYears == 0) { yield break; } } } }
输出结果为:
附官方链接:http://msdn.microsoft.com/zh-cn/library/9k7k7cf0.aspx
yield个人理解及简明示例
时间: 2024-09-30 19:15:03