C#编程(三十五)----------foreach和yield
枚舉
在foreach語(yǔ)句中使用枚舉,可以迭代集合中的元素,且無(wú)需知道集合中的元素個(gè)數(shù).
數(shù)組或集合實(shí)現(xiàn)帶GetEumerator()方法的IEumerable接口.GetEumerator()方法返回一個(gè)實(shí)現(xiàn)IEunmerable接口的枚舉.
GetEnumerator()方法用IEnumerable接口定義.foreach語(yǔ)句并不真的需要在集合類(lèi)中實(shí)現(xiàn)這個(gè)借口.有一個(gè)名為GetEnumerator()的方法,他返回實(shí)現(xiàn)了IEnumerator接口的對(duì)象就足夠了.
?
IEnumerator接口
foreach語(yǔ)句使用IEnumerator接口的方法和屬性,迭代集合中的所有元素.為此IEnumerator定義了Current屬性,來(lái)返回光標(biāo)所在的元素,該接口的MoveNext()方法移動(dòng)到集合的下一個(gè)元素上,如果有這個(gè)元素,該方法就返回true.如果集合不再有更多的元素,該方法就返回false.
這個(gè)借口的泛型版本IEnumerator<T>派生自接口IDisposable,因此定義了Dispose()方法,來(lái)清理枚舉器占用的資源.
?
foreach語(yǔ)句
C#的foreach語(yǔ)句不會(huì)解釋為IL代碼中的foreach語(yǔ)句.C#編譯器會(huì)把foreach語(yǔ)句轉(zhuǎn)換為IEnumerable接口的方法和屬性.案例:
int[] arr = { 1, 2, 3, 4, 5, 6, 7, 8 };
foreach (var item in arr)
{
???? Console.WriteLine(item);
}
很明顯,foreach語(yǔ)句很簡(jiǎn)潔,但是他的有點(diǎn)不僅僅在于此,它的效率也是很高的,不用考慮數(shù)組是幾維的.案例:
int[,] array = new int[8, 8];
??????????? for (int i = 0; i < array.GetLength(0); i++)
??????????? {
??????????????? for (int j = 0; j < array.GetLength(1); j++)
??????????????? {
Console.WriteLine(array[i,j].ToString());
??????????????? }
??????????? }
??????????? Console.ReadKey();
使用foreach:
foreach (int item in array)
??????????? {
??????????????? Console.WriteLine(item.ToString());
??????????? }
對(duì)于三維或者更多維,foreach語(yǔ)句不用發(fā)生任何變化,而對(duì)于for語(yǔ)句就要進(jìn)行修改了.
?
foreach完成類(lèi)型轉(zhuǎn)換操作,案例:
int[] array = new int[100];
??????????? ArrayList aList = new ArrayList();
??????????? aList.AddRange(array);
??????????? foreach (int item in aList)
??????????? {
??????????????? Console.WriteLine(item.ToString());
??????????? }
??????????? for (int i = 0; i < aList.Count; i++)
??????????? {
??????????????? int n = (int)aList[i];
??????????????? Console.WriteLine(n.ToString());
??????????? }
??????????? Console.ReadKey();
?
foreach并沒(méi)有增加資源使用,由于對(duì)于繼承了IEnumerable接口的數(shù)據(jù)類(lèi)型,才能使用foreach語(yǔ)句,那么對(duì)于使用foreach會(huì)訪(fǎng)問(wèn)IEnumerable接口中的GetEnumerator()方法來(lái)進(jìn)行枚舉,那么對(duì)應(yīng)如上的foreach語(yǔ)句,對(duì)應(yīng)的語(yǔ)句如下:
IEnumerator it = aList.GetEnumerator() as IEnumerator;
??????????? using (IDisposable disp = it as IDisposable)
??????????? {
??????????????? while (it.MoveNext())
??????????????? {
??????????????????? int elem = (int)it.Current;
??????????????????? Console.WriteLine(elem.ToString());
??????????????? }
??????????? }
也即是說(shuō)再出了foreach語(yǔ)句之后對(duì)于IEnumerator的對(duì)象也進(jìn)行IDispose處理.
?
foreach的兩種限制
不能修改枚舉成員:
int[] array = new int[100];
??????????? foreach (var item in array)
??????????? {
??????????????? item++;//這是錯(cuò)誤的,因?yàn)槊杜e成員是只讀的
??????????????? Console.WriteLine(item.ToString());
??????????? }
不要對(duì)集合進(jìn)項(xiàng)刪除操作:
int[] array = new int[100];
??????????? ArrayList alist = new ArrayList();
??????????? alist.AddRange(array);
??????????? foreach (var item in alist)
??????????? {
??????????????? alist.Remove(item);//這是錯(cuò)誤的
??????????????? Console.WriteLine(item.ToString());
??????????? }
對(duì)于刪除成員和修改成員可以使用for循環(huán)來(lái)處理,對(duì)于一個(gè)記錄集的多條數(shù)據(jù)刪除問(wèn)題,也是經(jīng)常出現(xiàn)的問(wèn)題,由于在一些記錄集中進(jìn)行刪除的時(shí)候,在刪除操作之后相應(yīng)的索引也發(fā)生了變化,這時(shí)候的刪除要反過(guò)來(lái)進(jìn)行刪除:
int[] array = new int[100];
??????????? ArrayList alist = new ArrayList();
??????????? alist.AddRange(array);
??????????? for (int i = alist.Count-1; i >=0; i--)
??????????? {
??????????????? int n = (int)alist[i];
??????????????? if (n==5)
??????????????? {
??????????????????? alist.RemoveAt(i);
??????????????? }
??????????????? Console.WriteLine(n.ToString());
??????????? }
?
除了上述提到的foreach的兩個(gè)約束外,foreach可以用于人和循環(huán).
?
yield語(yǔ)句
C#中的yield語(yǔ)句便于創(chuàng)建枚舉器.
yield語(yǔ)句的兩種形式:
1.yield return <expression>
2.yield break;
?
使用一個(gè)yield return語(yǔ)句返回集合的一個(gè)元素
包含yield語(yǔ)句的方法或?qū)傩允堑?span style="font-family:'Times New Roman';">.迭代器必須滿(mǎn)足下列要求:
a.返回類(lèi)型必須是IEnumerable,IEnumerable<T>,IEnumerator或IEnumerator<T>
b.他不能有任何ref或out參數(shù).
?
yield return語(yǔ)句不能位于try-catch塊;yield return語(yǔ)句可以位于try-finally的try中
yield return語(yǔ)句返回集合的一個(gè)元素,并移動(dòng)到下一個(gè)元素上.yield break可以停止迭代.
?
class Program
??? {
??????? static void Main(string[] args)
??????? {
??????????? HelloCollection hello = new HelloCollection();
??????????? foreach(string item in hello)
??????????? {
??????????????? Console.WriteLine(item);????????????????
??????????? }
??????????? Console.ReadKey();??
??????? }
?
??? }
??? public class HelloCollection
??? {
??????? public? IEnumerator<string> GetEnumerator()
??????? {
??????????? //yield return語(yǔ)句返回集合的一個(gè)元素,并移動(dòng)到下一個(gè)元素上
??????????? //yield break可以終止迭代
??????????? yield return "hello";
??????????? yield return "world";
??????? }
}
?
使用yield return語(yǔ)句實(shí)現(xiàn)以不同方式迭代集合的類(lèi):
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
?
namespace 枚舉
{
??? class Program
??? {
??????? static void Main(string[] args)
??????? {
??????????? MusicTitles music = new MusicTitles();
??????????? foreach(var item in music.GetEnumerator())
??????????? {
??????????????? Console.WriteLine(item);
??????????? }
??????????? Console.WriteLine();
??????????? foreach (string item in music.Reverse())
??????????? {
??????????????? Console.WriteLine(item);
??????????? }
??????????? Console.WriteLine();
??????????? foreach (var item in music.Subset(2,2))
??????????? {
??????????????? Console.WriteLine(item);
??????????? }
??????????? Console.ReadKey();??
??????? }
?
??? }
??? public class MusicTitles
??? {
??????? string[] names = {"a","b","c","d" };
??????? public IEnumerable<string> GetEnumerator()
??????? {
??????????? foreach (string item in names)
??????????? {
??????????????? yield return item;
??????????? }
??????? }
??????? public IEnumerable<string> Reverse()
??????? {
??????????? for (int i = 3; i >=0; i--)
??????????? {
??????????????? yield return names[i];
??????????? }
??????? }
??????? public IEnumerable<string> Subset(int index, int offert)
??????? {
??????????? for (int i = index; i < index+offert; i++)
??????????? {
??????????????? yield return names[i];
??????????? }
??????? }
??? }
}
轉(zhuǎn)載于:https://www.cnblogs.com/FinleyJiang/p/7602577.html
總結(jié)
以上是生活随笔為你收集整理的C#编程(三十五)----------foreach和yield的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 系统思考与《第五项修炼》
- 下一篇: 翁恺第三周2题