隨風設計

          隨風設計

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            11 隨筆 :: 0 文章 :: 0 評論 :: 0 Trackbacks

          本教程展示如何實現可與 foreach 語句一起使用的集合類。

          教程

          foreach 語句是循環訪問數組元素的方便方法。如果集合類已實現 System.Collections.IEnumeratorSystem.Collections.IEnumerable 接口,它還可以枚舉該集合的元素。

          示例 1

          下面的代碼示例闡釋如何編寫可與 foreach 一起使用的集合類。該類是字符串標記化拆分器,類似于 C 運行時庫函數 strtok。

          // tokens.cs
          using System;
          // The System.Collections namespace is made available:
          using System.Collections;
          
          // Declare the Tokens class:
          public class Tokens : IEnumerable
          {
             private string[] elements;
          
             Tokens(string source, char[] delimiters)
             {
                // Parse the string into tokens:
                elements = source.Split(delimiters);
             }
          
             // IEnumerable Interface Implementation:
             //   Declaration of the GetEnumerator() method 
             //   required by IEnumerable
             public IEnumerator GetEnumerator()
             {
                return new TokenEnumerator(this);
             }
          
             // Inner class implements IEnumerator interface:
             private class TokenEnumerator : IEnumerator
             {
                private int position = -1;
                private Tokens t;
          
                public TokenEnumerator(Tokens t)
                {
                   this.t = t;
                }
          
                // Declare the MoveNext method required by IEnumerator:
                public bool MoveNext()
                {
                   if (position < t.elements.Length - 1)
                   {
                      position++;
                      return true;
                   }
                   else
                   {
                      return false;
                   }
                }
          
                // Declare the Reset method required by IEnumerator:
                public void Reset()
                {
                   position = -1;
                }
          
                // Declare the Current property required by IEnumerator:
                public object Current
                {
                   get
                   {
                      return t.elements[position];
                   }
                }
             }
          
             // Test Tokens, TokenEnumerator
          
             static void Main()
             {
                // Testing Tokens by breaking the string into tokens:
                Tokens f = new Tokens("This is a well-done program.", 
                   new char[] {' ','-'});
                foreach (string item in f)
                {
                   Console.WriteLine(item);
                }
             }
          }

          輸出

          This
          is
          a
          well
          done
          program.

          代碼討論

          在前面的示例中,下列代碼用于 Tokens 化,方法是將“This is a well-done program.”拆分為標記(使用“”和“-”作為分隔符),并用 foreach 語句枚舉這些標記:

          Tokens f = new Tokens("This is a well-done program.", 
             new char[] {' ','-'});
          foreach (string item in f)
          {
             Console.WriteLine(item);
          }

          請注意,Tokens 在內部使用一個數組,自行實現 IEnumeratorIEnumerable。該代碼示例本可以利用數組本身的枚舉方法,但那會使本示例的目的失效。

          在 C# 中,集合類并非必須嚴格從 IEnumerable IEnumerator 繼承才能與 foreach 兼容;只要類有所需的 GetEnumeratorMoveNext、ResetCurrent 成員,便可以與 foreach 一起使用。省略接口的好處為,使您可以將 Current 的返回類型定義得比 object 更明確,從而提供了類型安全。

          例如,從上面的示例代碼開始,更改以下幾行:

          public class Tokens  // no longer inherits from IEnumerable
          public TokenEnumerator GetEnumerator()  // doesn't return an IEnumerator
          public class TokenEnumerator  // no longer inherits from IEnumerator
          public string Current  // type-safe: returns string, not object

          現在,由于 Current 返回字符串,當 foreach 語句中使用了不兼容的類型時,編譯器便能夠檢測到:

          foreach (int item in f)  // Error: cannot convert string to int

          省略 IEnumerable IEnumerator 的缺點是,集合類不再能夠與其他公共語言運行庫兼容的語言的 foreach 語句(或等效項)交互操作。

          您可以同時擁有二者的優點(C# 內的類型安全以及與兼容其他公共語言運行庫的語言的互操作性),方法是從 IEnumerableIEnumerator 繼承,并使用顯式接口實現,如下面的示例所示。

          示例 2

          本示例功能與“示例 1”等效,但它在維持與其他語言互操作性的同時還提供 C# 中的類型安全。

          // tokens2.cs
          using System;
          using System.Collections;
          
          public class Tokens: IEnumerable
          {
             private string[] elements;
          
             Tokens(string source, char[] delimiters)
             {
                elements = source.Split(delimiters);
             }
          
             // IEnumerable Interface Implementation:
          
             public TokenEnumerator GetEnumerator() // non-IEnumerable version
             {
                return new TokenEnumerator(this);
             }
          
             IEnumerator IEnumerable.GetEnumerator() // IEnumerable version
             {
                return (IEnumerator) new TokenEnumerator(this);
             }
          
             // Inner class implements IEnumerator interface:
          
             public class TokenEnumerator: IEnumerator
             {
                private int position = -1;
                private Tokens t;
          
                public TokenEnumerator(Tokens t)
                {
                   this.t = t;
                }
          
                public bool MoveNext()
                {
                   if (position < t.elements.Length - 1)
                   {
                      position++;
                      return true;
                   }
                   else
                   {
                      return false;
                   }
                }
          
                public void Reset()
                {
                   position = -1;
                }
          
                public string Current // non-IEnumerator version: type-safe
                {
                   get
                   {
                      return t.elements[position];
                   }
                }
          
                object IEnumerator.Current // IEnumerator version: returns object
                {
                   get
                   {
                      return t.elements[position];
                   }
                }
             }
          
             // Test Tokens, TokenEnumerator
          
             static void Main()
             {
                Tokens f = new Tokens("This is a well-done program.", 
                   new char [] {' ','-'});
                foreach (string item in f) // try changing string to int
                {
                   Console.WriteLine(item);
                }
             }
          }
          posted on 2006-08-17 11:36 曹賢 閱讀(236) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 孙吴县| 综艺| 定州市| 新竹县| 个旧市| 茂名市| 齐齐哈尔市| 明水县| 右玉县| 莱西市| 博白县| 东兰县| 昭通市| 岳普湖县| 呼和浩特市| 中方县| 三亚市| 衡阳市| 遂宁市| 安阳县| 淄博市| 保定市| 长白| 天等县| 涞水县| 建水县| 松原市| 台北市| 衡阳县| 陵川县| 秭归县| 元江| 瑞昌市| 灵山县| 库尔勒市| 托克托县| 北流市| 雷山县| 满城县| 石楼县| 通辽市|