程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C# 2.0:使用匿名方法、迭代程序和局部類來創建優雅的代碼(2)

C# 2.0:使用匿名方法、迭代程序和局部類來創建優雅的代碼(2)

編輯:關於C語言

此外,由於每個迭代程序都保持單獨的迭代狀態 ,所以多個客戶端可以執行單獨的並發迭代。通過實現 IEnumerable,諸如數組 和隊列這樣的數據結構可以支持這種超常規的迭代。在 foreach 循環中生成的代 碼調用類的 GetEnumerator 方法簡單地獲得一個 IEnumerator 對象,然後將其 用於 while 循環,從而通過連續調用它的 MoveNext 方法和當前屬性遍歷集合。 如果您需要顯式地遍歷集合,您可以直接使用 IEnumerator(不用求助於 foreach 語句)。

但是使用這種方法有一些問題。首先,如果集合包含值 類型,則需要對它們進行裝箱和拆箱才能獲得項,因為 IEnumerator.Current 返 回一個對象。這將導致潛在的性能退化和托管堆上的壓力增大。即使集合包含引 用類型,仍然會產生從對象向下強制類型轉換的不利結果。雖然大多數開發人員 不熟悉這一特性,但是在 C# 1.0 中,實際上不必實現 IEnumerator 或 IEnumerable 就可以為每個循環實現迭代程序模式。編譯器將選擇調用強類型化 版本,以避免強制類型轉換和裝箱。結果是,即使在 1.0 版本中,也可能沒有導 致性能損失。

為了更好地闡明這個解決方案並使其易於實現,Microsoft .Net 框架 2.0 在 System.Collections.Generics 命名空間中定義了一般的類型 安全的 IEnumerable <ItemType> 和 IEnumerator <ItemType> 接 口:

public interface IEnumerable<ItemType>
{
  IEnumerator<ItemType> GetEnumerator();
}
public interface IEnumerator<ItemType> : IDisposable
{
  ItemType Current{get;}
  bool MoveNext();
}

除 了利用泛型之外,新的接口與其前身還略有差別。與 IEnumerator 不同, IEnumerator <ItemType> 是從 IDisposable 派生而來的,並且沒有 Reset 方法。圖 2 中的代碼顯示了實現 IEnumerable <string> 的簡單 city 集合,而圖 3 顯示了編譯器在跨越 foreach 循環的代碼時如何使用該接口 。圖 2 中的實現使用了名為 MyEnumerator 的嵌套類,它將一個引用作為構造參 數返回給要枚舉的集合。MyEnumerator 清楚地知道 city 集合(本例中的一個數 組)的實現細節。MyEnumerator 類使用 m_Current 成員變量維持當前的迭代狀 態,此成員變量用作數組的索引。

Figure 2Implementing IEnumerable<string>

public class CityCollection : IEnumerable<string>
{
  string[] m_CitIEs = {"New York","Paris","London"};
  public IEnumerator<string> GetEnumerator()
  {
   return new MyEnumerator(this);
  }
  //Nested class definition
  class MyEnumerator : IEnumerator<string>
  {
    CityCollection m_Collection;
   int m_Current;
    public MyEnumerator(CityCollection collection)
   {
      m_Collection = collection;
     m_Current = -1;
    }
   public bool MoveNext()
   {
     m_Current++;
     if(m_Current < m_Collection.m_CitIEs.Length)
      return true;
      else
      return false;
   }
   public string Current
   {
     get
     {
       if(m_Current == -1)
        throw new InvalidOperationException();
      return m_Collection.m_CitIEs[m_Current];
     }
   }
    public void Dispose(){}
  }
}

圖 2

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved