1. 程式人生 > >C#2.0-迭代器應用

C#2.0-迭代器應用

介紹 迭代器作為匿名方法存在是很不明顯的,但是其強大的特性現在被引入到Csharp2.0版本中了。迭代器有資格作為語法構造的一部分出現並不意味著從.NET 1.x過渡到2.0版本後通用語言執行時與.NET中間語言指令集發生了改變。只是如同匿名方法一樣,所有的這些魔法都隱藏到編譯器中了。為了理解下面的CSharp2.0中迭代器的原理,我們將深入到其內部中,並適當的運用一些在2.0版本中出現的基本特性,接著我們還將分析其中編譯器的內部工作機制,最後我們還將掌握在CSharp2.0使用迭代器的一些高階技術。 Csharp1.x中迭代器,列舉,列舉器以及使用迭代設計模式 在我們分析CSharp1和CSharp2的列舉器之前。我們有必要知道什麼是可列舉的以及什麼是列舉器。我們在談及一個物件是可列舉的是指如果一個物件包含或引用了一個物件集和如果一個元素屬於這個集合那麼我們能夠使用CSsharp關鍵字’foreach
列舉出來。實現了System.Collections.IEnumerable介面的例項化的類都是可列舉的。下面我們將會看到,具有某些可列舉特徵並不意味著一定滿足這個條件。

如果一個類實現了System.Collections.IEnumerable介面那麼它就是一個列舉器。這裡是一些介面的定義:

namespace System.Collections
{
//為介面繫結屬性
[System.Runtime.InteropServices.GuidAttribute(“496B0ABE-CDEE-11d3-88E8-00902754C43A”)]
//注意這裡是為了執行時反射
//我們看看該配件的自描述
//使用了GuidAttribute類,這裡我使用了Reflector查看了該類的實現
//該類是這樣描述的
//[AttributeUsage(AttributeTargets.Delegate | (AttributeTargets.Interface | (AttributeTargets.Enum | (AttributeTargets.Struct | (AttributeTargets.Class | AttributeTargets.Assembly)))), Inherited=false)]
//ArrtibuteTargets是列舉型別
//指出該類綁定了代理,介面,列舉,結構,類以及配件,並且不可繼承
//這裡的繼承含義不是類的派生,而是指出屬性不可繼承,這意味假設存在派生類並對其類重新進行了屬性繫結,那麼派生類所繫結的屬性將覆蓋基類所繫結的屬性
//不過,該類同時也是一個不可繼承的類,這在類的定義中可以看到含有一個sealed修飾符

public interface IEnumerable
{
    [System.Runtime.InteropService.DispIdAttribute(
252)]
    System.Collections.IEumerator GetEnumerator();
}


//為介面繫結屬性
[System.Runtime.InteropServices.GuidAttribute("496B0ABF-CDEE-11d3-88E8-00902754C43A")]
public interface IEumerator
{
    
//返回當前集合中的元素
object Current
    
{
        
get;
    }

    
//返回值true表示迭代器成功前進到集合中的下一個元素
    
//返回值false表示已經位於集合的末尾
bool MoveNext();
    
//恢復初始化指向的位置
void Reset();
}

}


客戶端呼叫IEnumerable.GetEnumerator()方法實際上是通過IEnumeratorCurrent屬性,該屬性在派生類EnumeratorConcret實現,並例項化為EnumeratorConcret。當MoveNext()Reset()方法被呼叫的時候,列舉器將保持當前的索引,這樣客戶端就可以通過Current屬性訪問集合中的元素。它的UML檢視看起來像這樣:

對於那些知曉GoF設計模式的人來說,CSharp迭代器的實現是顯而易見的,這個設計模式被命名為迭代; 一個例子

    這有一個使用CSharp語法實現迭代的例子。Person類是一個可列舉的類。PersonsEnumerator類是一個列舉器類。注意如果類實現了以上兩種介面那麼Person類就具有了可列舉和列舉器兩種身份。無論怎樣,我們將看到一種更優雅的實現類的方法(這裡我們遵循了一條重要的面向物件原則:建立一個可複用的類【物件】)

using System;
using System.Collections;
public class Persons : IEnumerable
{
    
private class PersonsEnumerator : IEnumerator
    
{
        
private int index = -1;
        
private Persons P;
        
public PersonsEnumerator(Persons P)
        
{
            
this.P = P;
        }

        
public bool MoveNext()
        
{
            index
++;
            
return P.m_Names.Length;
        }

        
public void Reset()
        
{
            index 
= -1;
        }

        
public object Current
        
{
            
get
            
{
                
return P.m_Names[index];
            }

        }

    }

    
    
string[] m_Names;
    
public Persons(params string[] Names)
    
{
        m_Names 
= new string[Names.Length];
        Names.CopyTo(m_Names,
0);
    }

    
private string this[int index]
    
{
        
get
        
{
            
return m_Names[index];
        }

        
set
        
{
            m_Names[index] 
= value;
        }

    }

}


class Program
{
    
static void Main(string[] args)
    
{
        Persons arrPersons 
= new Persons(“Michel”,”Christine”,”Mathieu”,”Julien”);
        
foreach (string s in arrPersons)
        
{
            Console.WriteLine(s);
            Console.ReadLine();
        }

    }

}


該程式將輸出: Michel
Christine
Mathieu
Julien
這段程式碼中的大部分語句用來實現列舉器的索引行為,我們更希望看到CSharp2.0達到同樣功能卻戲劇性的縮小的程式碼數量。 注意:C#編譯器類似如下程式碼來解釋foreach關鍵字 class Program
{
    
static void Main(string[] args)
    
{
          Persons arrPersons 
= new Persons(“Michel”,”Christine”,”Mathieu”,”Julien”);
          IEnumerator e 
= arrPersons.GetEnumerator();
          While (e.MoveNext())
          
{
       Console.WriteLine((
string)e.Current);
       Console.ReadLine();
          }

    }

}


單一列舉包含多個列舉構造器
    一個可列舉類不一定要服從實現IEnumerable介面。這個責任可以被委託到其他類中實現。例如:
using System;
    
using System.Collections;
    
public class Persons    //這裡沒有實現IEnumerable介面
{
        
private class PersonsEnumerator :IEnumerator
        
{
            …
        }

相關推薦

C#2.0-應用

介紹 迭代器作為匿名方法存在是很不明顯的,但是其強大的特性現在被引入到Csharp2.0版本中了。迭代器有資格作為語法構造的一部分出現並不意味著從.NET 1.x過渡到2.0版本後通用語言執行時與.NET中間語言指令集發生了改變。只是如同匿名方法一樣,所有的這

C#2.0

2.0 blog .com 運行 技術分享 color urn 做了 繼承 叠代器 叠代器模式是和為模式的一種範例,我們訪問數據序列中所有的元素,不用關心序列是什麽類型。從數據管道中數據經過一系列不同的轉換或過濾後從管道的另一端出來。 像數組、集合等已經內置了叠代器

C++ : 插入,流,反向,移動應用例項

插入迭代器:back_inserter、front_inserter、inserter 流迭代器:istream_iterator(讀取輸入流)、ostream_iterator(讀取輸出流) 反向迭代器:rbegin()、rend()、crbegin()、crend()  

Python 目錄 匿名函式的相關應用 應用 python_控制檯輸出帶顏色的文字方法 time & datetime 模組 random模組 subprocess模組 hashlib模組 json&pickle模組 shelve模組 xml模組 sys模組 os 模組 sh

    匿名函式的相關應用 迭代器 應用 python_控制檯輸出帶顏色的文字方法 collections模組(提供了幾個額外的資料型別:) time & datetime 模組 random模組 subprocess模組(通過Python去執行一條系統命令或指令碼

(D14-2)Python-

迭代器 Iterator Vs for 直到StopIteraation 停止,不撞南牆不回頭。 什麼是迭代器? 訪問迭代物件的工具 迭代器是指 iter (函式返回物件) 迭代器可以用 next(函式獲取可迭代物件的資料) 迭代器函

C++容器,,容器的介面卡

容器 順序容器 主要靠下標和迭代器進行操作。順序性的主要靠下標,鏈式的靠迭代器訪問。 包含了順序型的容器和鏈式的容器。 連續型的包括: vector:向量,可以快速擴充套件和刪除元素,在隊尾的操作有優勢! deque:雙端佇列,可以快速的從隊首和隊尾新增或者刪

C#基礎:原理

在迭代器塊中,使用yield關鍵字返回給foreach迴圈中使用的值,下面是迭代器的原理。SimpleList()是迭代器塊。  public static IEnumerable SimpleList()//迭代器使用yield return返回值給foreach  

陣列的使用(2) ---方法

迭代器方法:指對陣列中的每個元素都應用一個函式,可以返回一個值、一組值、或者一個新陣列。 不生成新陣列的迭代器方法 ① forEach() 接收一個函式作為引數,對於陣列中的每個元素都使用該函式 var num = [1,2,3,4,5,6,7]

C++之STL(iterator)

1、vector #include <iostream> #include <vector> int main() { std::vector<char> charVector; int x; for (x=0; x&l

deque原始碼2(deque、deque的資料結構)

deque的迭代器 deque是分段連續空間,維持其"整體連續"的假象任務,落在了迭代器的operator++和operator--兩個運運算元身上。 對於operator:1、必須能夠指出分段連續空間(即緩衝區)在哪裡          2、必須能夠判斷自己是否已經處於其

我所理解的設計模式(C++實現)——模式(Iterator Pattern)

概述:         在現在的電視機中,我們使用[後一個]和[前一個]按鈕可以很方便的換臺,當按下[後一個]按鈕時,將切換到下一個預置的頻道。想象一下在陌生的城市中的旅店中看電視。當改變頻道時,重要的不是幾頻道,而是節目內容。如果對一個頻道的節目不感興趣,那麼可以換下一個頻道,而不需要知道它是幾頻道。  

c++中刪除指向的元素後,指向的被刪除元素後面的元素

1.  C++向容器中插入和刪除元素的時候,迭代器會失效,下面是正確刪除容器元素的做法 void StatsServer::removeExpiredWorkers() { size_t expiredWorkerCount = 0; size_t expiredU

C++ STL之

一. 什麼是迭代器? 迭代器是STL中行為類似指標的設計模式,它可以提供了一種對容器中的物件的訪問方法;並且它沒有暴露容器中內部的表述方式。  例如STL中的map和set,它們的底層是一顆紅黑樹(一種平衡樹),而當你用迭代器去對他們進行訪問時,原本在紅黑樹中的二叉樹結構

C/C++容器和理解

為什麼要有容器?    我知道有陣列,但陣列有一個弊端,它是固定的,不可變。這個經常會導致出現數組越界導常的錯誤。並且還需要事先知道這個陣列的長度才可以定義。 但很多時候,我們並不知道未來將會發生什麼,所以我們創造了容器,它是不固定的,可變的,可以根據元素的增加而增加,每次增加原陣列的1.5倍。為什麼是1.5

C++容器:的操作

共通操作: *iter 返回迭代器 iter 所指向的元素的引用 iter->mem 對 iter 進行解引用,獲取指定元素中名為 mem 的成員。等效於 (*iter).mem ++iter iter++ 給 iter 加 1,使其指向容器裡的下

C++ 自定義(實現++遞增兩格)

//效果每次迭代器加移動兩格 #pragma once //MyIterator.h #include <iterator> #include <exception> template<typename Container&g

C++容器的iterator遇到刪除函式erase時

      C++中添加了各種各樣的STL容器,不僅數量眾多,而且功能強大,如果能夠正常使用,可以使我們省去諸多時間。迭代器(iterator)是一種物件,它能夠用來遍歷標準模板庫容器中的部分或全部元素,每個迭代器物件代表容器中的確定的地址,簡單點就是每個“節點”物件的“指標

[C++]高效使用的一些建議

迭代器 本文介紹四種迭代器的使用細節,已經相互轉換的方法,從而提高對迭代的理解和使用。 1. iterator優於const_iterator, const_reverse_iterator, reverse_iterator itera

4.C#2.0(未完成)

  4.1迭代器塊      迭代器塊就是產生值的有序序列的語句塊,迭代器塊通過一個/多個yield語句區別於常規語句:           -yield return 語句產生迭代的下一個值   &nb

6.2 C# 2:利用 yield 語句簡化

    1 class Program 2 { 3 static void Main(string[] args) 4 { 5 object[] values = new object[]