C#?迭代器分部類(lèi)與索引器詳情
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è)類(lèi)型繼承了接口IEnumerable,或者繼承了泛型接口IEnumerable或者繼承了泛型接口IEnumerable的任何構(gòu)造類(lèi)型,那么久成這個(gè)類(lèi)型時(shí)可枚舉的
- 常見(jiàn)的可枚舉類(lèi)型:集合,數(shù)組,字符串類(lèi)String,標(biāo)識(shí)動(dòng)態(tài)列表的泛型類(lè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)迭代可枚舉類(lèi)型的過(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)器或其他代碼塊,使用戶能夠在類(lèi)或結(jié)構(gòu)中支持Foreach迭代,而不必實(shí)現(xiàn)整個(gè)IEnumerable接口,只需要一個(gè)類(lèi)型化的方法GetEnumerator(),不需要處理設(shè)計(jì)模式
- 迭代器是C#可以提供的最簡(jiǎn)單的設(shè)計(jì)模式。
- 設(shè)計(jì)模式(Design pattern/behavorial pattern)是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過(guò)分類(lèi)編目的、典賣(mài)設(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ō)明:迭代器返回值類(lèi)型必須為IEnumerable(迭代類(lèi)成員)和IEnumerator(迭代類(lèi))一個(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遍歷,要保證是可枚舉類(lèi)型的
{
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();
}
}
}
分布類(lèi)概述及其使用
分布類(lèi)定義:將類(lèi)的定義拆分到兩個(gè)或多個(gè)資源文件中。每個(gè)源文件包含類(lèi)定義的一部分,編譯應(yīng)用程序時(shí)將把所有部分組合起來(lái),這就是分布類(lèi)。
應(yīng)用場(chǎng)合(partial):
- 處理大型項(xiàng)目時(shí),使一個(gè)類(lèi)分布于多個(gè)獨(dú)立文件中,可以讓多位程序員同時(shí)對(duì)該類(lèi)進(jìn)行處理;
- 使用自動(dòng)生成的源時(shí),無(wú)需重新創(chuàng)建源文件便可將代碼添加到類(lèi)中。
vs在創(chuàng)建windows窗體和web服務(wù)包裝代碼等時(shí)都是用此方法。開(kāi)發(fā)人員無(wú)須編譯vs所創(chuàng)建的文件,即可創(chuàng)建使用這些類(lèi)的代碼。
實(shí)現(xiàn)過(guò)程:
- 通過(guò)多個(gè)部分來(lái)定義一個(gè)類(lèi)
- partial關(guān)鍵字:必須直接放在class的前面
- 分部類(lèi)聲明的每個(gè)部分都必須包含partial修飾符,并且器聲明必須與其他部分位于同一命名空間。
- partial修飾符說(shuō)明在其他位置可能還有同一個(gè)類(lèi)型聲明的其他部分。但是這些其他部分并非必須存在:如果只有一個(gè)類(lèi)型聲明,包含partial修飾符也是有效的。
- 當(dāng)分部類(lèi)聲明指定了可訪問(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_分部類(lèi)
{
//利用分部類(lèi)實(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)用分部類(lèi)的第一部分——階乘計(jì)算結(jié)果:{0}", a.factorial(num));
int index = 3;
Console.WriteLine("調(diào)用分部類(lèi)的第二部分——冪指函數(shù)計(jì)算結(jié)果:{0}", a.power(num, index));
Console.ReadKey();
}
}
}注意事項(xiàng) :
- 分部類(lèi)時(shí),同一個(gè)類(lèi)型各個(gè)部分的所有分部類(lèi)類(lèi)型定義都必須使用partial進(jìn)行修飾,必須具有相同的可訪問(wèn)性。
- 同一個(gè)類(lèi)型的各個(gè)部分的所有分部類(lèi)型定義都必須在同一程序集合同一模塊中進(jìn)行定義。分部類(lèi)定義不能跨越多個(gè)模塊。
- 使用partial關(guān)鍵字表明可在命名空間內(nèi)定義該類(lèi)、結(jié)構(gòu)或接口的其他部分,各個(gè)部分可以指定不同的基接口,最終類(lèi)型將實(shí)現(xiàn),所有分部聲明所列出的全部接口。
索引器概述及聲明
可以通過(guò)小標(biāo)訪問(wèn)數(shù)組中的元素的方式就是索引器
索引器允許類(lèi)或結(jié)構(gòu)的實(shí)例按照與數(shù)組相同的方式進(jìn)行索引。索引器的聲明和屬性的聲明非常相似,不同的是他們的訪問(wèn)器采用參數(shù)——索引器的聲明除了包括索引關(guān)鍵字(index)的聲明外,還包括this關(guān)鍵字。使得向數(shù)組那樣對(duì)對(duì)象使用下標(biāo),并提供了通過(guò)索引方式方便第訪問(wèn)類(lèi)的數(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,必須在抽象類(lèi)中聲明抽象索引器
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _4_索引器概述及聲明
{
//屬性聲明
public class Clerk
{
private string name; //字段聲明,專(zhuān)供類(lèi)內(nèi)部使用,所以聲明為私有的
public string Name //屬性為外部事務(wù),可以供其他類(lèi)進(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)
{
}
}
}索引器在類(lèi)中的使用
- 索引器允許用戶按照處理數(shù)組的方式索引類(lèi),訪問(wèn)時(shí)有兩種形式
- 使用索引器可直接訪問(wèn)類(lèi)實(shí)例:將數(shù)組聲明為public成員并直接訪問(wèn)它的成員;
實(shí)例:1、訪問(wèn)類(lèi)實(shí)例(容量為10的整型數(shù)組為例)2、訪問(wèn)類(lèi)成員(以星期演示)
using System;
namespace _5_索引器在類(lèi)中的使用
{
public class indexText //訪問(wèn)類(lèi)的實(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)類(lèi)成員
{
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)類(lèi)實(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),利用類(lèi)成員進(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# 迭代器分部類(lèi)與索引器詳情的文章就介紹到這了,更多相關(guān)C# 迭代器,索引器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#編程簡(jiǎn)單實(shí)現(xiàn)生成PDF文檔的方法示例
這篇文章主要介紹了C#編程簡(jiǎn)單實(shí)現(xiàn)生成PDF文檔的方法,結(jié)合實(shí)例形式分析了C#生成PDF文檔的具體步驟與相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-07-07
Unity實(shí)現(xiàn)物體跟隨鼠標(biāo)移動(dòng)
這篇文章主要為大家詳細(xì)介紹了Unity實(shí)現(xiàn)物體跟隨鼠標(biāo)移動(dòng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01
C#實(shí)現(xiàn)Ruby的負(fù)數(shù)索引器
這篇文章主要介紹了C#實(shí)現(xiàn)Ruby的負(fù)數(shù)索引器的相關(guān)代碼和使用方法,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下2016-07-07
c# DevExpress gridcontrol日期行的顯示格式設(shè)置
這篇文章主要介紹了c# DevExpress gridcontrol日期行的顯示格式設(shè)置,需要的朋友可以參考下2017-02-02

