C#?迭代器分部類與索引器詳情
1、迭代器
- 迭代器(iterator)解決的是集合訪問(wèn)的問(wèn)題,提供一種方法順序訪問(wèn)一個(gè)集合對(duì)象中的各個(gè)元素,而不暴露對(duì)象內(nèi)部標(biāo)識(shí)。迭代器還有一個(gè)別名:游標(biāo)(cursor)
- foreach語(yǔ)句與迭代器的關(guān)系:Foreach循環(huán)語(yǔ)句可以用來(lái)迭代枚舉的集合中的所有元素,又稱foreach迭代語(yǔ)句
- 可枚舉的:C#中,如果某個(gè)類型繼承了接口IEnumerable,或者繼承了泛型接口IEnumerable或者繼承了泛型接口IEnumerable的任何構(gòu)造類型,那么久成這個(gè)類型時(shí)可枚舉的
- 常見(jiàn)的可枚舉類型:集合,數(shù)組,字符串類String,標(biāo)識(shí)動(dòng)態(tài)列表的泛型類List等
- Foreach語(yǔ)句可以簡(jiǎn)化C#內(nèi)置迭代器的使用復(fù)雜性,編譯froeach語(yǔ)句,會(huì)生成調(diào)用GetEnumerator和MoveNext方法以及Current屬性的代碼,這些方法和屬性恰是C#內(nèi)置迭代器所提供的。
- ILDASM外部工具的添加方法(中間語(yǔ)言反匯編的工具)
方法1:
打開(kāi)新添加的外部工具:
方法2
查看Foreach執(zhí)行中間語(yǔ)言
- 中間語(yǔ)言:intermediate language
- ILDASM: intermediate language decompile assembly
foreach實(shí)現(xiàn)過(guò)程總結(jié)
foreach語(yǔ)句是微軟提供的支持內(nèi)置迭代器的語(yǔ)句法糖,編譯foreach語(yǔ)句后生產(chǎn)的代碼與使用迭代器的代碼完全一致
調(diào)用GetEnumerator()方法獲得迭代器——調(diào)用IEnumerator.MoveNext()——調(diào)用IEnumerator.Current()
Foreach循環(huán)迭代可枚舉類型的過(guò)程:
1、通過(guò)調(diào)用IEnumerator接口和IEnumerator的引用
2、IEnuerator調(diào)用MoveNext方法
3) ①True:IEnumerator的Current屬性獲取對(duì)象的應(yīng)用,用于foreach循環(huán)
②false 結(jié)束
4、重復(fù)2、3步知道MoveNext返回false
實(shí)現(xiàn)迭代器最常用的方法
迭代器可用于方法、屬性訪問(wèn)器或其他代碼塊,使用戶能夠在類或結(jié)構(gòu)中支持Foreach迭代,而不必實(shí)現(xiàn)整個(gè)IEnumerable接口,只需要一個(gè)類型化的方法GetEnumerator(),不需要處理設(shè)計(jì)模式
- 迭代器是C#可以提供的最簡(jiǎn)單的設(shè)計(jì)模式。
- 設(shè)計(jì)模式(Design pattern/behavorial pattern)是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過(guò)分類編目的、典賣設(shè)計(jì)經(jīng)驗(yàn)總結(jié)。使用設(shè)計(jì)模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。
- .Net Framework有自己的IEnumerator接口,使用的迭代器的作用很明確,及可以做到不暴露集合的內(nèi)部接口,又可讓外部代碼同名地方訪問(wèn)集合內(nèi)部的數(shù)據(jù)。 2.1 創(chuàng)建迭代器最常用的方法 是對(duì)IEnumerable接口實(shí)現(xiàn)GetEnumerator方法創(chuàng)建最簡(jiǎn)單的迭代塊說(shuō)明:迭代器返回值類型必須為IEnumerable(迭代類成員)和IEnumerator(迭代類)一個(gè)迭代器會(huì)出現(xiàn)一個(gè)或者多個(gè)yield語(yǔ)句,與一般語(yǔ)句塊的區(qū)別:yield return 一次返回迭代的下一個(gè)袁旭yield break 指出這個(gè)迭代的結(jié)束
```csharp using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Collections; // 需要引用的命名空間 namespace 實(shí)現(xiàn)迭代器常用的方法 { class Program { public static IEnumerable SimpleDemo() { yield return "string1"; yield return "string2"; yield return "string3"; yield break; //運(yùn)行到此處就終止了迭代 yield return "string4"; yield return "string5"; } //月份迭代 public class Months : IEnumerable //為了使用Foreach遍歷,要保證是可枚舉類型的 { string[] month = { "Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Nov", "Dec" }; public IEnumerator GetEnumerator() { for(int i=0;i<month.Length;i++) { yield return month[i]; } } } static void Main(string[] args) { foreach (string item in SimpleDemo()) { Console.WriteLine(item); } Months mon = new Months(); foreach(string m in mon) { Console.WriteLine(m); } Console.ReadKey(); } } }
分布類概述及其使用
分布類定義:將類的定義拆分到兩個(gè)或多個(gè)資源文件中。每個(gè)源文件包含類定義的一部分,編譯應(yīng)用程序時(shí)將把所有部分組合起來(lái),這就是分布類。
應(yīng)用場(chǎng)合(partial):
- 處理大型項(xiàng)目時(shí),使一個(gè)類分布于多個(gè)獨(dú)立文件中,可以讓多位程序員同時(shí)對(duì)該類進(jìn)行處理;
- 使用自動(dòng)生成的源時(shí),無(wú)需重新創(chuàng)建源文件便可將代碼添加到類中。
vs在創(chuàng)建windows窗體和web服務(wù)包裝代碼等時(shí)都是用此方法。開(kāi)發(fā)人員無(wú)須編譯vs所創(chuàng)建的文件,即可創(chuàng)建使用這些類的代碼。
實(shí)現(xiàn)過(guò)程:
- 通過(guò)多個(gè)部分來(lái)定義一個(gè)類
- partial關(guān)鍵字:必須直接放在class的前面
- 分部類聲明的每個(gè)部分都必須包含partial修飾符,并且器聲明必須與其他部分位于同一命名空間。
- partial修飾符說(shuō)明在其他位置可能還有同一個(gè)類型聲明的其他部分。但是這些其他部分并非必須存在:如果只有一個(gè)類型聲明,包含partial修飾符也是有效的。
- 當(dāng)分部類聲明指定了可訪問(wèn)性(借助訪問(wèn)修飾符:public、protected、internal private)時(shí),它必須與其他部分所指定的可訪問(wèn)性一致。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace _3_分部類 { //利用分部類實(shí)現(xiàn)階乘與冪指數(shù)運(yùn)算 partial class arithmetic //階乘 { public int factorial(int num) { int factorialval = 1; for(int i = num; i>0;i--) { factorialval *= i; } return factorialval; } } partial class arithmetic //冪指數(shù)運(yùn)算 { public int power(int num, int index) { int result = 1; for (int i = 0; i < index; i++) { result *= num; } return result; } } class Program { static void Main(string[] args) { arithmetic a = new arithmetic(); int num = 5; Console.WriteLine("調(diào)用分部類的第一部分——階乘計(jì)算結(jié)果:{0}", a.factorial(num)); int index = 3; Console.WriteLine("調(diào)用分部類的第二部分——冪指函數(shù)計(jì)算結(jié)果:{0}", a.power(num, index)); Console.ReadKey(); } } }
注意事項(xiàng) :
- 分部類時(shí),同一個(gè)類型各個(gè)部分的所有分部類類型定義都必須使用partial進(jìn)行修飾,必須具有相同的可訪問(wèn)性。
- 同一個(gè)類型的各個(gè)部分的所有分部類型定義都必須在同一程序集合同一模塊中進(jìn)行定義。分部類定義不能跨越多個(gè)模塊。
- 使用partial關(guān)鍵字表明可在命名空間內(nèi)定義該類、結(jié)構(gòu)或接口的其他部分,各個(gè)部分可以指定不同的基接口,最終類型將實(shí)現(xiàn),所有分部聲明所列出的全部接口。
索引器概述及聲明
可以通過(guò)小標(biāo)訪問(wèn)數(shù)組中的元素的方式就是索引器
索引器允許類或結(jié)構(gòu)的實(shí)例按照與數(shù)組相同的方式進(jìn)行索引。索引器的聲明和屬性的聲明非常相似,不同的是他們的訪問(wèn)器采用參數(shù)——索引器的聲明除了包括索引關(guān)鍵字(index)的聲明外,還包括this關(guān)鍵字。使得向數(shù)組那樣對(duì)對(duì)象使用下標(biāo),并提供了通過(guò)索引方式方便第訪問(wèn)類的數(shù)據(jù)信息的方法。(屬性的作用就是保護(hù)字段,對(duì)字段的取值和賦值進(jìn)行限定)
- 虛擬索引器:virtual
- 外部索引器:extern 因?yàn)橥獠克饕髀暶鞑惶峁┤魏螌?shí)際的實(shí)現(xiàn),所以他的每個(gè)訪問(wèn)器生摩納哥都由一個(gè)分號(hào)組成。
- 抽象索引器:abstract 當(dāng)要定義為抽象索引器時(shí),必須提供空的get和set,必須在抽象類中聲明抽象索引器
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace _4_索引器概述及聲明 { //屬性聲明 public class Clerk { private string name; //字段聲明,專供類內(nèi)部使用,所以聲明為私有的 public string Name //屬性為外部事務(wù),可以供其他類進(jìn)行交流使用,所以聲明為公共的 { get { return name; } set { name = value; } } private char gender; public char Gender { get { if (gender != '男' && gender != '女') gender = '男'; return gender; } set { gender = value; } } //索引器聲明1 //private int[] myint = new int[10]; //public int this[int index] //{ // get { return myint[index]; } //單獨(dú)存在為只讀 // set { myint[index] = value; } //單獨(dú)存在為只寫(xiě) ,兩個(gè)同時(shí)存在為讀寫(xiě) //} //聲明一個(gè)虛擬的索引器 //private int[] myint2 = new int[10]; //public virtual int this[int index2] //{ // get { return myint2[index2]; } // set { myint2[index2] = value; } //} // 聲明一個(gè)外部索引器 public extern int this[int index] { get; set; } } // 抽象索引器聲明 abstract class indexEaxmple { public abstract int this[int index] { get; set; } } class Program { static void Main(string[] args) { } } }
索引器在類中的使用
- 索引器允許用戶按照處理數(shù)組的方式索引類,訪問(wèn)時(shí)有兩種形式
- 使用索引器可直接訪問(wèn)類實(shí)例:將數(shù)組聲明為public成員并直接訪問(wèn)它的成員;
實(shí)例:1、訪問(wèn)類實(shí)例(容量為10的整型數(shù)組為例)2、訪問(wèn)類成員(以星期演示)
using System; namespace _5_索引器在類中的使用 { public class indexText //訪問(wèn)類的實(shí)例 { private int[] array = new int[10]; public int this[int index] { get { if (index < 0 || index > 10) return 0; else return array[index]; } set { if (index >= 0 && index < 10) array[index] = value; } } } public class weekIndex //訪問(wèn)類成員 { string[] week = { "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日" }; private int getDay(string weekText) { int i = 0; foreach(string day in week) { if (day == weekText) return i+1; i++; } return -1; } public int this[string week] { get { return getDay(week); } } } class Program { static void Main(string[] args) { Console.WriteLine("訪問(wèn)類實(shí)例的結(jié)果"); indexText Arr = new indexText(); Arr[-5] = 5; Arr[0] = 15; Arr[2] = 60; Arr[11] = 65; Console.WriteLine("Arr[-5]={0}", Arr[-5]); Console.WriteLine("Arr[0]={0}", Arr[0]); Console.WriteLine("Arr[1]={0}", Arr[1]); Console.WriteLine("Arr[2]={0}", Arr[2]); Console.WriteLine("Arr[11]={0}", Arr[11]); Console.WriteLine("訪問(wèn)累成員結(jié)果"); weekIndex we = new weekIndex(); Console.WriteLine(we["星期三"]); Console.WriteLine(we["星期四"]); Console.WriteLine(we["星期八"]); Console.WriteLine(we["星期0"]); Console.ReadKey(); } } }
索引器在接口中的使用
索引器可以作為接口成員來(lái)聲明,單接口中的索引器聲明不包括任何訪問(wèn)修飾符,這是因?yàn)榻涌诓话ㄈ魏尉幊坛绦蛘Z(yǔ)句,所以get和set訪問(wèn)器沒(méi)有程序主題,因此,訪問(wèn)索引器的用途是指示索引器時(shí)讀寫(xiě)、只讀還是只寫(xiě)
using System; namespace _6_索引器在接口中的使用 { public interface iTextIndex { int this[int index] { get; set; } } class indexText:iTextIndex { // 演示容量為10的數(shù)組,對(duì)實(shí)例成員的訪問(wèn) private int[] array = new int[10]; public int this[int index] { get { if (index < 0 || index >= 10) return 0; else return array[index]; } set { if (index > 0 && index < 10) array[index] = value; } } } class Program { static void Main(string[] args) { indexText Arr = new indexText(); Arr[-1] = 5; Arr[4] = 10; Arr[9] = 20; Arr[14] = 30; for(int i=-1;i<15;i=i+5) { Console.WriteLine("Arr[{0}]={1}", i, Arr[i]); } Console.ReadKey(); } } }
小結(jié)及任務(wù)實(shí)施
索引器實(shí)現(xiàn)QQ狀態(tài)的訪問(wèn),利用類成員進(jìn)行訪問(wèn),得出QQ狀態(tài)對(duì)應(yīng)的索引值
using System; namespace 本章小結(jié)及任務(wù)實(shí)施 { public class QQStateIndex { string [] qqState = { "在線", "離線", "忙碌", "Q我", "隱身" }; private int getState(string stateText) { int i= 0; foreach(string stateString in qqState) { if (stateString == stateText) return i; i++; } return -1; } public int this[string stateString] { get { return getState(stateString); } } } class Program { static void Main(string[] args) { QQStateIndex qs = new QQStateIndex(); Console.WriteLine(qs["在線"]); Console.WriteLine(qs["忙碌"]); Console.WriteLine(qs["睡眠"]); Console.ReadKey(); } } }
到此這篇關(guān)于C# 迭代器分部類與索引器詳情的文章就介紹到這了,更多相關(guān)C# 迭代器,索引器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C# Winform實(shí)現(xiàn)捕獲窗體最小化、最大化、關(guān)閉按鈕事件的方法
這篇文章主要介紹了C# Winform實(shí)現(xiàn)捕獲窗體最小化、最大化、關(guān)閉按鈕事件的方法,可通過(guò)重寫(xiě)WndProc來(lái)實(shí)現(xiàn),需要的朋友可以參考下2014-08-08詳解C#如何對(duì)ListBox控件中的數(shù)據(jù)進(jìn)行操作
這篇文章主要為大家詳細(xì)介紹了C#中對(duì)ListBox控件中的數(shù)據(jù)進(jìn)行的操作,主要包括添加、刪除、清空、選擇、排序等,感興趣的小伙伴可以了解下2024-03-03C#使用表達(dá)式樹(shù)(LambdaExpression)動(dòng)態(tài)更新類的屬性值(示例代碼)
這篇文章主要介紹了C#使用表達(dá)式樹(shù)(LambdaExpression)動(dòng)態(tài)更新類的屬性值,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-01-01C#面向?qū)ο笾M實(shí)現(xiàn)商城購(gòu)物功能
這篇文章主要為大家詳細(xì)介紹了C#面向?qū)ο笾M實(shí)現(xiàn)商城購(gòu)物功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02-
最新評(píng)論