using System; using System.Collections.Generic; using System.Reflection; using System.Text.RegularExpressions; using System.Linq; namespace Test { //C#的yield关键字由来以久,如果我没有记错的话,应该是在C# 2.0中被引入的。 //相信大家此关键字的用法已经了然于胸,很多人也了解yield背后的“延迟赋值”机制。 //但是即使你知道这个机制,你也很容易在不经意间掉入它制造的陷阱。 // //对于上面的现象,很多人一眼就可以看出这是由于yield背后的“延迟赋值”机制导致, //但是不可否认我们会不经意间犯这种错误。为了让大家对这个问题有稍微深刻的认识, //我们还是简单来谈谈“延迟赋值”。延迟赋值(Delay|Lazy Evaluation)又被称为延迟计算。 //为了避免不必要的计算导致的性能损失,和LINQ查询一样,yield关键字并不会导致后值语句的立即执行, //而是转换成一个“表达式”。只有等到需要的那一刻(进行迭代)的时候,表达式被才被执行。 class Program { static void Main(string[] args) { IEnumerable<Vector> vectors = GetVectors(); foreach (var vector in vectors) { vector.X = 4; vector.Y = 4; } //赋值没成功 还是输出原来的结果 //从运行后的结过我们可以看出,Vector对象被创建了6次,来自于两次迭代。 //一次是对Vector元素的重新赋值,另一次源自对Vector元素的输出。 //由于两次迭代造作的并不是同一批对象,才会导致X和Y属性依然“保持”着原始的值。 foreach (var vector in vectors) { Console.WriteLine(vector); } Console.WriteLine("分割线-------------------------------------------"); IEnumerable<Vector> vectorsNow = GetVectors().ToList(); foreach (var vector in vectorsNow) { vector.X = 4; vector.Y = 4; } foreach (var vector in vectorsNow) { Console.WriteLine(vector); } Console.ReadLine(); } static IEnumerable<Vector> GetVectors() { yield return new Vector(1, 1); yield return new Vector(2, 3); yield return new Vector(3, 3); } } public class Vector { public double X { get; set; } public double Y { get; set; } public Vector(double x, double y) { Console.WriteLine("构造函数"); this.X = x; this.Y = y; } public override string ToString() { return string.Format("X = {0}, Y = {1}", this.X, this.Y); } } }