案例一:
public class Order { public DateTime StartDate { get; set; } public DateTime EndDate { get; set; } public IEnumerableDateRange { get { for (DateTime day = StartDate; day <= EndDate; day = day.AddDays(1)) { yield return day; } } } }
Order order = new Order { StartDate = DateTime.Now, EndDate = DateTime.Now.AddDays(31) }; #region 不使用迭代器 for (DateTime day = order.StartDate; day <= order.EndDate; day = day.AddDays(1)) { Console.WriteLine(day); } #endregion Console.WriteLine("********************************************"); #region 使用迭代器 foreach (var dateTime in order.DateRange) { Console.WriteLine(dateTime); } #endregion
案例二:
class Program { static void Main(string[] args) { string path = ""; using (TextReader reader = File.OpenText(path)) { string line; while ((line = reader.ReadLine()) != null) { Console.WriteLine(line); } } //下面是对上面这段代码的封装 #region 版本1 TextReader tr = File.OpenText(path); ReadFile(tr, Console.WriteLine);// ,这里之所以可以这样简写委托实例,是因为 Console.WriteLine() 方法有很多重载,利用了 "Method Group"的概念 #endregion #region 版本2 foreach (var line in ReadLines(path)) { Console.WriteLine(line); } #endregion Console.ReadKey(); } #region 版本1 static void ReadFile(TextReader reader, Actionaction) { string line; while ((line = reader.ReadLine()) != null) { action(line); } reader.Close(); reader.Dispose(); } #endregion //这个版本的弊端是:reader 在方法内部创建,限制了编码格式,如果调用者突然想用其他编码方式,则无法使用该方法 #region 版本2 static IEnumerable ProcessFile(string path) { using (TextReader reader = File.OpenText(path)) { string line; while ((line = reader.ReadLine()) != null) { yield return line; } } } #endregion //如果我们想使用不用的编码格式呢? //所以 reader 的创建还是要交换给调用者 //但是这个方案最大的弊端是:需要调用者自己清理 reader #region 版本3 static IEnumerable ReadLines(TextReader reader) { string line; while ((line = reader.ReadLine()) != null) { yield return line; } } #endregion //利用委托,延迟 reader 的创建 //即,我们只有在需要的时候才去获取资源 #region 终极版本 static IEnumerable ReadLines(Func provider) { using (TextReader reader = provider()) { string line; while ((line = reader.ReadLine()) != null) { yield return line; } } } static IEnumerable ReadLines(string path) { return ReadLines(path, Encoding.UTF8); } static IEnumerable ReadLines(string path, Encoding encoding) { return ReadLines(() => new StreamReader(path, encoding)); } #endregion }
案例三:
class Program { static void Main(string[] args) { List list = new List { 1, 2, 3, 4, 5, 6, 7 }; //当我们调用 where 方法时,我们理所当然的认为会立刻进行参数的校验 //但实际上不是,因为在 where 方法里面有 yield return 语句,也就是说:这个 where 方法是一个迭代器块 //而迭代器块具有延迟执行的特性 //意思就是,当我们调用 where 方法的时候,并不会立刻执行方法内部的参数校验, //而是要等到 foreach 语句的 in 指令时,才会执行 //同时,由于 yield return 语句返回的类型必须是实现了 IEnumerable 或者 IEnumerable接口的类型 var result = WhereGood(list, s => s % 2 == 0); foreach (var i in result) { Console.WriteLine(i); } Console.ReadKey(); } #region 不好的写法 static IEnumerable Where (IEnumerable source, Predicate predicate) { if (source == null || predicate == null) { Console.WriteLine("入参错误!"); throw new Exception("入参错误"); } foreach (var item in source) { if (predicate(item)) { yield return item; } } } #endregion #region 好的写法,校验参数和逻辑代码分开写 static IEnumerable WhereGood (IEnumerable source, Predicate predicate) { if (source == null || predicate == null) { Console.WriteLine("入参错误!"); throw new Exception("入参错误"); } //同样,这里不会立刻执行 GoWhere() 方法,直到 执行到 foreach 中的 in return GoWhere(source, predicate); } static IEnumerable GoWhere (IEnumerable source, Predicate predicate) { foreach (var item in source) { if (predicate(item)) { yield return item; } } } #endregion