程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> [c#基礎]集合foreach的必要條件和自定義集合

[c#基礎]集合foreach的必要條件和自定義集合

編輯:C#入門知識

引言 最近翻看了之前的學習筆記,看到foreach,記得當時老師講的時候,有點犯渾,不是很明白,這好比,上小學時,你不會乘法口訣,但是隨著時間的增長,你不自覺的都會了,也悟出個小道理,有些東西,你當時不太懂,但隨著你的閱歷和經驗的增長,有那麼一天你會恍然大悟,哦,原來是這樣。   自定義集合類 提到foreach就不得不說集合,那麼就先從自定義的集合開始吧。   復制代碼  1 using System;  2 using System.Collections.Generic;  3 using System.Linq;  4 using System.Text;  5 using System.Threading.Tasks;  6   7 namespace Wolfy.自定義集合  8 {  9     /// <summary> 10     /// 自定義集合類 11     /// </summary> 12     public class MyArrayList 13     { 14         /// <summary> 15         /// 集合的容量屬性 成倍數增加0,4,8,且只讀 16         /// </summary> 17         public int Capacity 18         { 19             get 20             { 21                 return this.objArray.Length == 0 ? 0 : this.index > this.objArray.Length ? this.objArray.Length * 2 : this.objArray.Length; 22             } 23         } 24         /// <summary> 25         /// 集合實際元素個數 且只讀 26         /// </summary> 27         public int Count 28         { 29             get 30             { 31                 return this.index; 32             } 33         } 34         private int index; 35         private object[] objArray; 36         public MyArrayList() 37         { 38             index = 0; 39             //初始化0長度的數組 40             this.objArray = new object[0]; 41         } 42         /// <summary> 43         /// 添加元素 44         /// </summary> 45         /// <param name="value">元素值</param> 46         public void Add(object value) 47         { 48             if (index >= this.objArray.Length) 49             { 50                 object[] newArray = index == 0 ? new object[this.objArray.Length + 4] : new object[this.objArray.Length * 2]; 51                 objArray.CopyTo(newArray, 0); 52                 objArray = newArray; 53                 objArray[index++] = value; 54             } 55             else 56             { 57                 objArray[index++] = value; 58             } 59         } 60         /// <summary> 61         /// 添加數組 62         /// </summary> 63         /// <param name="objs"></param> 64         public void AddRange(object[] objs) 65         { 66             for (int i = 0; i < objs.Length; i++) 67             { 68                 this.Add(objs[i]); 69             } 70         } 71     } 72 } 復制代碼 不知道自定義的集合和ArrayList是否一樣,可以簡單的測試一下。   復制代碼  1 using System;  2 using System.Collections;  3 using System.Collections.Generic;  4 using System.Linq;  5 using System.Text;  6 using System.Threading.Tasks;  7   8 namespace Wolfy.自定義集合  9 { 10     class Program 11     { 12         static void Main(string[] args) 13         { 14             ArrayList list = new ArrayList(); 15             //MyArrayList list = new MyArrayList(); 16             Console.WriteLine("count:" + list.Count); 17             Console.WriteLine("Capacity:" + list.Capacity); 18             list.Add(1); 19             list.Add(1); 20             Console.WriteLine("count:" + list.Count); 21             Console.WriteLine("Capacity:" + list.Capacity); 22             list.Add(1); 23             list.Add(1); 24             list.Add(1); 25             Console.WriteLine("count:" + list.Count); 26             Console.WriteLine("Capacity:" + list.Capacity); 27             list.Add(1); 28             list.Add(1); 29             list.Add(1); 30             list.Add(1); 31             list.Add(1); 32             list.Add(1); 33             Console.WriteLine("count:" + list.Count); 34             Console.WriteLine("Capacity:" + list.Capacity); 35             object[] arr = { 1, 2, 3, 4, 5, 6 }; 36             list.AddRange(arr); 37             Console.WriteLine("count:" + list.Count); 38             Console.WriteLine("Capacity:" + list.Capacity); 39             Console.Read(); 40         } 41     } 42 } 復制代碼 此時是.Net中的ArrayList,結果:     自定義的集合,結果:       輸出結果一樣,那麼現在用foreach遍歷,自定義集合中的元素。F6編譯,會提示錯誤。       foreach語句  其實foreach是怎樣工作的呢?   眾所周知foreach中in後面的對象應該是實現IEnumerable接口的,程序運行時本質是在調用IEnumerable的GetEnumerator函數來返回一個IEnumerator對象,foreach就是利用IEnumerator對象的Current,MoveNext和Reset成員來進行一段數據的枚舉。簡單的代碼實現如下:   1             //System.Collections下的IEnumerator 2             IEnumerator enumerator = this.objArray.GetEnumerator(); 3             while (enumerator.MoveNext()) 4             { 5                 Console.WriteLine(enumerator.Current); 6             } 將這個代碼放在自定義集合中,定義一個方法GetArray(),然後測試一下   復制代碼  1         /// <summary>  2         /// 得到所有的元素  3         /// </summary>  4         public void GetArray()  5         {  6             //System.Collections下的IEnumerator  7             IEnumerator enumerator = this.objArray.GetEnumerator();  8             while (enumerator.MoveNext())  9             { 10                 Console.Write(enumerator.Current+“,”); 11             } 12         } 復制代碼 測試結果:       你運行會發現多出很多逗號,原因是執行後,enumerator沒有被Dispose掉,而繼承IDisposable的迭代器(IEnumerator)在foreach結束後會被正確處理掉(調用Dispose方法)。   自定義集合實現IEnumerable接口 實現IEnumerable接口必須實現它裡面的成員GetEnumerator()方法:   1         public IEnumerator GetEnumerator() 2         { 3             throw new NotImplementedException(); 4         } 該方法的返回值為實現了IEnumerator接口的類的對象。那麼現在需要定義一個實現了該接口的類。   復制代碼  1 using System;  2 using System.Collections;  3 using System.Collections.Generic;  4 using System.Linq;  5 using System.Text;  6 using System.Threading.Tasks;  7   8 namespace Wolfy.自定義集合  9 { 10     public class MyEnumerator : IEnumerator 11     { 12         /// <summary> 13         /// 返回當前指針指向的元素的值 14         /// </summary> 15         public object Current 16         { 17             get { throw new NotImplementedException(); } 18         } 19         /// <summary> 20         /// 將指針向前移動1位,並判斷當前位有沒有元素.指針默認在-1位置 21         /// </summary> 22         /// <returns></returns> 23         public bool MoveNext() 24         { 25             throw new NotImplementedException(); 26         } 27         /// <summary> 28         /// 重置 29         /// </summary> 30         public void Reset() 31         { 32             throw new NotImplementedException(); 33         } 34     } 35 } 復制代碼 迭代需要數組參數,在構造函數中將自定義集合中的數組傳進來,並且在MoveNext中需要判斷指針是否移動到數組的末尾,那麼需要數組的長度。 MyArrayList中GetEnumerator()方法實現   1         public IEnumerator GetEnumerator() 2         { 3             return new MyEnumerator(this.objArray, this.Count); 4         } MyEnumerator類   復制代碼  1 using System;  2 using System.Collections;  3 using System.Collections.Generic;  4 using System.Linq;  5 using System.Text;  6 using System.Threading.Tasks;  7   8 namespace Wolfy.自定義集合  9 { 10     public class MyEnumerator : IEnumerator 11     { 12         /// <summary> 13         /// 指針的默認位置 14         /// </summary> 15         private int index = -1; 16         private object[] objArray; 17         /// <summary> 18         /// 數組長度 19         /// </summary> 20         private int count; 21         public MyEnumerator(object[] objArray, int count) 22         { 23  24             this.objArray = objArray; 25             this.count = count; 26         } 27         /// <summary> 28         /// 返回當前指針指向的元素的值 29         /// </summary> 30         public object Current 31         { 32             get { return this.objArray[index]; } 33         } 34         /// <summary> 35         /// 將指針向前移動1位,並判斷當前位有沒有元素.指針默認在-1位置 36         /// </summary> 37         /// <returns></returns> 38         public bool MoveNext() 39         { 40             index++;//指針首先向前移動一位 41             if (index < this.count) 42             { 43                 return true; 44             } 45             else 46             { 47                 return false; 48             } 49         } 50         /// <summary> 51         /// 重置 52         /// </summary> 53         public void Reset() 54         { 55             index = -1; 56         } 57     } 58 }

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved