C#?迭代器分部類與索引器詳情
1、迭代器
- 迭代器(iterator)解決的是集合訪問的問題,提供一種方法順序訪問一個集合對象中的各個元素,而不暴露對象內(nèi)部標(biāo)識。迭代器還有一個別名:游標(biāo)(cursor)
- foreach語句與迭代器的關(guān)系:Foreach循環(huán)語句可以用來迭代枚舉的集合中的所有元素,又稱foreach迭代語句
- 可枚舉的:C#中,如果某個類型繼承了接口IEnumerable,或者繼承了泛型接口IEnumerable或者繼承了泛型接口IEnumerable的任何構(gòu)造類型,那么久成這個類型時可枚舉的
- 常見的可枚舉類型:集合,數(shù)組,字符串類String,標(biāo)識動態(tài)列表的泛型類List等


- Foreach語句可以簡化C#內(nèi)置迭代器的使用復(fù)雜性,編譯froeach語句,會生成調(diào)用GetEnumerator和MoveNext方法以及Current屬性的代碼,這些方法和屬性恰是C#內(nèi)置迭代器所提供的。
- ILDASM外部工具的添加方法(中間語言反匯編的工具)
方法1:





打開新添加的外部工具:

方法2


查看Foreach執(zhí)行中間語言



- 中間語言:intermediate language
- ILDASM: intermediate language decompile assembly

foreach實現(xiàn)過程總結(jié)
foreach語句是微軟提供的支持內(nèi)置迭代器的語句法糖,編譯foreach語句后生產(chǎn)的代碼與使用迭代器的代碼完全一致
調(diào)用GetEnumerator()方法獲得迭代器——調(diào)用IEnumerator.MoveNext()——調(diào)用IEnumerator.Current()
Foreach循環(huán)迭代可枚舉類型的過程:
1、通過調(diào)用IEnumerator接口和IEnumerator的引用
2、IEnuerator調(diào)用MoveNext方法
3) ①True:IEnumerator的Current屬性獲取對象的應(yīng)用,用于foreach循環(huán)
②false 結(jié)束
4、重復(fù)2、3步知道MoveNext返回false
實現(xiàn)迭代器最常用的方法
迭代器可用于方法、屬性訪問器或其他代碼塊,使用戶能夠在類或結(jié)構(gòu)中支持Foreach迭代,而不必實現(xiàn)整個IEnumerable接口,只需要一個類型化的方法GetEnumerator(),不需要處理設(shè)計模式
- 迭代器是C#可以提供的最簡單的設(shè)計模式。
- 設(shè)計模式(Design pattern/behavorial pattern)是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過分類編目的、典賣設(shè)計經(jīng)驗總結(jié)。使用設(shè)計模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。
- .Net Framework有自己的IEnumerator接口,使用的迭代器的作用很明確,及可以做到不暴露集合的內(nèi)部接口,又可讓外部代碼同名地方訪問集合內(nèi)部的數(shù)據(jù)。 2.1 創(chuàng)建迭代器最常用的方法 是對IEnumerable接口實現(xiàn)GetEnumerator方法創(chuàng)建最簡單的迭代塊說明:迭代器返回值類型必須為IEnumerable(迭代類成員)和IEnumerator(迭代類)一個迭代器會出現(xiàn)一個或者多個yield語句,與一般語句塊的區(qū)別:yield return 一次返回迭代的下一個袁旭yield break 指出這個迭代的結(jié)束
```csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections; // 需要引用的命名空間
namespace 實現(xiàn)迭代器常用的方法
{
class Program
{
public static IEnumerable SimpleDemo()
{
yield return "string1";
yield return "string2";
yield return "string3";
yield break; //運行到此處就終止了迭代
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();
}
}
}
分布類概述及其使用
分布類定義:將類的定義拆分到兩個或多個資源文件中。每個源文件包含類定義的一部分,編譯應(yīng)用程序時將把所有部分組合起來,這就是分布類。
應(yīng)用場合(partial):
- 處理大型項目時,使一個類分布于多個獨立文件中,可以讓多位程序員同時對該類進(jìn)行處理;
- 使用自動生成的源時,無需重新創(chuàng)建源文件便可將代碼添加到類中。
vs在創(chuàng)建windows窗體和web服務(wù)包裝代碼等時都是用此方法。開發(fā)人員無須編譯vs所創(chuàng)建的文件,即可創(chuàng)建使用這些類的代碼。
實現(xiàn)過程:
- 通過多個部分來定義一個類
- partial關(guān)鍵字:必須直接放在class的前面
- 分部類聲明的每個部分都必須包含partial修飾符,并且器聲明必須與其他部分位于同一命名空間。
- partial修飾符說明在其他位置可能還有同一個類型聲明的其他部分。但是這些其他部分并非必須存在:如果只有一個類型聲明,包含partial修飾符也是有效的。
- 當(dāng)分部類聲明指定了可訪問性(借助訪問修飾符:public、protected、internal private)時,它必須與其他部分所指定的可訪問性一致。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _3_分部類
{
//利用分部類實現(xiàn)階乘與冪指數(shù)運算
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ù)運算
{
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)用分部類的第一部分——階乘計算結(jié)果:{0}", a.factorial(num));
int index = 3;
Console.WriteLine("調(diào)用分部類的第二部分——冪指函數(shù)計算結(jié)果:{0}", a.power(num, index));
Console.ReadKey();
}
}
}注意事項 :
- 分部類時,同一個類型各個部分的所有分部類類型定義都必須使用partial進(jìn)行修飾,必須具有相同的可訪問性。
- 同一個類型的各個部分的所有分部類型定義都必須在同一程序集合同一模塊中進(jìn)行定義。分部類定義不能跨越多個模塊。
- 使用partial關(guān)鍵字表明可在命名空間內(nèi)定義該類、結(jié)構(gòu)或接口的其他部分,各個部分可以指定不同的基接口,最終類型將實現(xiàn),所有分部聲明所列出的全部接口。
索引器概述及聲明
可以通過小標(biāo)訪問數(shù)組中的元素的方式就是索引器
索引器允許類或結(jié)構(gòu)的實例按照與數(shù)組相同的方式進(jìn)行索引。索引器的聲明和屬性的聲明非常相似,不同的是他們的訪問器采用參數(shù)——索引器的聲明除了包括索引關(guān)鍵字(index)的聲明外,還包括this關(guān)鍵字。使得向數(shù)組那樣對對象使用下標(biāo),并提供了通過索引方式方便第訪問類的數(shù)據(jù)信息的方法。(屬性的作用就是保護(hù)字段,對字段的取值和賦值進(jìn)行限定)
- 虛擬索引器:virtual
- 外部索引器:extern 因為外部索引器聲明不提供任何實際的實現(xiàn),所以他的每個訪問器生摩納哥都由一個分號組成。
- 抽象索引器:abstract 當(dāng)要定義為抽象索引器時,必須提供空的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]; } //單獨存在為只讀
// set { myint[index] = value; } //單獨存在為只寫 ,兩個同時存在為讀寫
//}
//聲明一個虛擬的索引器
//private int[] myint2 = new int[10];
//public virtual int this[int index2]
//{
// get { return myint2[index2]; }
// set { myint2[index2] = value; }
//}
// 聲明一個外部索引器
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ù)組的方式索引類,訪問時有兩種形式
- 使用索引器可直接訪問類實例:將數(shù)組聲明為public成員并直接訪問它的成員;
實例:1、訪問類實例(容量為10的整型數(shù)組為例)2、訪問類成員(以星期演示)
using System;
namespace _5_索引器在類中的使用
{
public class indexText //訪問類的實例
{
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 //訪問類成員
{
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("訪問類實例的結(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("訪問累成員結(jié)果");
weekIndex we = new weekIndex();
Console.WriteLine(we["星期三"]);
Console.WriteLine(we["星期四"]);
Console.WriteLine(we["星期八"]);
Console.WriteLine(we["星期0"]);
Console.ReadKey();
}
}
}索引器在接口中的使用
索引器可以作為接口成員來聲明,單接口中的索引器聲明不包括任何訪問修飾符,這是因為接口不包括任何編程程序語句,所以get和set訪問器沒有程序主題,因此,訪問索引器的用途是指示索引器時讀寫、只讀還是只寫
using System;
namespace _6_索引器在接口中的使用
{
public interface iTextIndex
{
int this[int index]
{
get;
set;
}
}
class indexText:iTextIndex
{
// 演示容量為10的數(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;
}
}
}
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ù)實施
索引器實現(xiàn)QQ狀態(tài)的訪問,利用類成員進(jìn)行訪問,得出QQ狀態(tài)對應(yīng)的索引值
using System;
namespace 本章小結(jié)及任務(wù)實施
{
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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
c# DevExpress gridcontrol日期行的顯示格式設(shè)置
這篇文章主要介紹了c# DevExpress gridcontrol日期行的顯示格式設(shè)置,需要的朋友可以參考下2017-02-02

