国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

C# 傳統遍歷與迭代器

2019-11-06 06:16:23
字體:
來源:轉載
供稿:網友

引言:

  在C# 1.0中我們經常使用foreach來遍歷一個集合中的元素,然而一個類型要能夠使用foreach關鍵字來對其進行遍歷必須實現IEnumerable或IEnumerable接口,(之所以來必須要實現IEnumerable這個接口,是因為foreach是迭代語句,要使用foreach必須要有一個迭代器才行的,然而IEnumerable接口中就有IEnumerator GetEnumerator()方法是返回迭代器的,所以實現了IEnumerable接口,就必須實現GetEnumerator()這個方法來返回迭代器,有了迭代器就自然就可以使用foreach語句了),然而在C# 1.0中要獲得迭代器就必須實現IEnumerable接口中的GetEnumerator()方法,然而要實現一個迭代器就必須實現IEnumerator接口中的bool MoveNext()和void Reset()方法,然而 C# 2.0中提供 yield關鍵字來簡化迭代器的實現,這樣在C# 2.0中如果我們要自定義一個迭代器就容易多了。下面就具體介紹了C# 2.0 中如何提供對迭代器的支持.

一、迭代器的介紹

  迭代器大家可以想象成數據庫的游標,即一個集合中的某個位置,C# 1.0中使用foreach語句實現了訪問迭代器的內置支持,使用foreach使我們遍歷集合更加容易(比使用for語句更加方便,并且也更加容易理解),foreach被編譯后會調用GetEnumerator來返回一個迭代器,也就是一個集合中的初始位置(foreach其實也相當于是一個語法糖,把復雜的生成代碼工作交給編譯器去執行)。

二、C#1.0如何實現迭代器

  在C# 1.0 中實現一個迭代器必須實現IEnumerator接口,下面代碼演示了傳統方式來實現一個自定義的迭代器:

using System;using System.Collections;namespace 迭代器Demo{ class PRogram { static void Main(string[] args) { Friends friendcollection = new Friends(); foreach (Friend f in friendcollection) { Console.WriteLine(f.Name); } Console.Read(); } } /// <summary> /// 朋友類 /// </summary> public class Friend { private string name; public string Name { get { return name; } set { name = value; } } public Friend(string name) { this.name = name; } } /// <summary> /// 朋友集合 /// </summary> public class Friends : IEnumerable { private Friend[] friendarray; public Friends() { friendarray = new Friend[] { new Friend("張三"), new Friend("李四"), new Friend("王五") }; } // 索引器 public Friend this[int index] { get { return friendarray[index]; } } public int Count { get { return friendarray.Length; } } // 實現IEnumerable<T>接口方法 public IEnumerator GetEnumerator() { return new FriendIterator(this); } } /// <summary> /// 自定義迭代器,必須實現 IEnumerator接口 /// </summary> public class FriendIterator : IEnumerator { private readonly Friends friends; private int index; private Friend current; internal FriendIterator(Friends friendcollection) { this.friends = friendcollection; index = 0; } #region 實現IEnumerator接口中的方法 public object Current { get { return this.current; } } public bool MoveNext() { if (index + 1 > friends.Count) { return false; } else { this.current = friends[index]; index++; return true; } } public void Reset() { index = 0; } #endregion }}

運行結果: 這里寫圖片描述

三、使用C#2.0的新特性簡化迭代器的實現

  在C# 1.0 中要實現一個迭代器必須實現IEnumerator接口,這樣就必須實現IEnumerator接口中的MoveNext、Reset方法和Current屬性,從上面代碼中看出,為了實現FriendIterator迭代器需要寫40行代碼,然而在C# 2.0 中通過yield return語句簡化了迭代器的實現,下面看看C# 2.0中簡化迭代器的代碼:

using System;using System.Collections;namespace CSharp2._0版迭代器{ class Program { #region C# 2.0 使用 yield return 語句實現迭代器 public class Car { public string BrandName { get; set; } public Car() { } public Car(string name) { this.BrandName = name; } } public class Cars : IEnumerable { private Car[] carArray; public Cars() { carArray = new Car[] { new Car("Toyota"), new Car("Nissna"), new Car("Audi") }; } /// <summary> /// 索引器 /// </summary> public Car this[int index] { get { return carArray[index]; } } public int Count { get { return carArray.Length; } } // C# 2.0中簡化迭代器的實現 public IEnumerator GetEnumerator() { for (int index = 0; index < carArray.Length; index++) { // 使用yield return 就不需要額外定義一個類似FriendIterator的迭代器來實現IEnumerator // 在C# 2.0中只需要使用下面語句就可以實現一個迭代器 yield return carArray[index]; } } } #endregion static void Main(string[] args) { #region C#2.0的新特性簡化迭代器的實現 Cars carsCollection = new Cars(); foreach (Car car in carsCollection) { Console.WriteLine(car.BrandName); } Console.ReadKey(); #endregion } }}

 在上面代碼中有一個yield return 語句,這個語句的作用就是告訴編譯器GetEnumerator方法不是一個普通的方法,而是實現一個迭代器的方法,當編譯器看到yield return語句時,編譯器知道需要實現一個迭代器,所以編譯器生成中間代碼時為我們生成了一個IEnumerator接口的對象,大家可以通過Reflector工具進行查看:  這里寫圖片描述 從上面截圖可以看出,yield return 語句其實是C#中提供的另一個語法糖,簡化我們實現迭代器的源代碼,把具體實現復雜迭代器的過程交給編譯器幫我們去完成。

四、迭代器的執行過程 這里寫圖片描述

五、迭代器的延遲計算 從第四部分中迭代器的執行過程中可以知道迭代器是延遲計算的, 因為迭代的主體在MoveNext()中實現(因為在MoveNext()方法中訪問了集合中的當前位置的元素),Foreach中每次遍歷執行到in的時候才會調用MoveNext()方法,所以迭代器可以延遲計算,下面通過一個示例來演示迭代器的延遲計算:

using System;using System.Collections.Generic;namespace CSharp2._0迭代器的執行過程{ class Program { #region 迭代器的延遲計算 public static IEnumerable<int> WithNoIterator() { List<int> list = new List<int>(); for (int i = 0; i < 5; i++) { Console.WriteLine("當前i的值為:{0}", i); if (i > 1) { list.Add(i); } } return list; } public static IEnumerable<int> WithIterator() { for (int i = 0; i < 5; i++) { Console.WriteLine("在WithIterator方法中的, 當前i的值為:{0}", i); if (i > 1) { yield return i; } } } #endregion static void Main(string[] args) { // 測試一 Console.WriteLine("測試一:"); WithNoIterator(); Console.WriteLine(); // 測試二 Console.WriteLine("測試二:"); WithIterator(); Console.WriteLine(); // 測試三 Console.WriteLine("測試三:"); foreach (int j in WithIterator()) { Console.WriteLine("在main輸出語句中,當前i的值為:{0}", j); } Console.ReadKey(); } }}

運行結果: 這里寫圖片描述

測試一:正如我們期望的那樣輸出了結果,列出來是為了更好說明測試二迭代器的延遲計算 測試二:什么都沒有輸出,我們用Reflector工具查看WithIterator()方法: 這里寫圖片描述   代碼中調用WithIterator()時,對于編譯器而言,就是實例化了一個< WithIterator > d_1的對象(< WithIterator > d_1類是編譯看到WithIterator方法中包含Yield return 語句生成的一個迭代器類),所以運行測試一的代碼時,控制臺中什么都不輸出。

測試三:為什么2,3,4會運行兩次的呢?下面具體為大家分析下為什么會有這樣的結果。我們用Reflector工具查看MoveNext():

這里寫圖片描述

這里寫圖片描述

  從截圖中可以看到,將下面的輸出語句

Console.WriteLine(“在WithIterator方法中的, 當前i的值為:{0}”, i);

生成到迭代器的 MoveNext()方法體中了,所以

public static IEnumerable<int> WithIterator() { for (int i = 0; i < 5; i++) { Console.WriteLine("在WithIterator方法中的, 當前i的值為:{0}", i); if (i > 1) { yield return i; } } }

WithIterator方法中的值,被依次輸出到控制臺了。

參考 “迭代器的執行過程”圖中的示意,程序在執行到yield return i 關鍵字時才會返回下面的foreach循環,將i值帶回給j,輸出

Console.WriteLine("在main輸出語句中,當前i的值為:{0}", j);

后繼續執行for循環,所以 2,3,4被輸出到屏幕2次

六、總結   本文主要介紹了C# 2.0中通過yield return語句對迭代器實現的簡化,然而對于編譯器而言,卻沒有簡化,它同樣生成了一個類去實現IEnumerator接口,只是我們開發人員去實現一個迭代器得到了簡化而已。通過本文大家可以對迭代器有一個進一步的認識,并且迭代器的延遲計算也是Linq的基礎。

C#穩固基礎:傳統遍歷與迭代器

C#基礎知識系列]專題十二:迭代器

不能不說的C#特性-迭代器(上)及一些研究過程中的副產品

不能不說的C#特性-迭代器(下),yield以及流的延遲計算


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 岢岚县| 清流县| 东乌珠穆沁旗| 吕梁市| 延安市| 南投市| 普陀区| 安远县| 栾川县| 开化县| 乳源| 小金县| 邯郸县| 桃源县| 满洲里市| 临漳县| 双牌县| 清涧县| 阳原县| 桦南县| 上犹县| 巴彦淖尔市| 手游| 高尔夫| 陆良县| 天气| 报价| 吉水县| 富川| 上犹县| 安多县| 新乡县| 宕昌县| 富顺县| 镇江市| 青龙| 迁安市| 乌鲁木齐县| 嘉善县| 云和县| 隆林|