程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#高級程序設計(七)——迭代

C#高級程序設計(七)——迭代

編輯:C#入門知識

.NET使用IEnumerator接口和IEnumerable接口(以及它們的泛型版本)實現迭代器模式,迭代是LINQ的核心。
接口定義如下:
[csharp]
public interface IEnumerable 

    IEnumerator GetEnumerator(); 

 
public interface IEnumerator 

    object Current { get; } 
    bool MoveNext(); 
    void Reset(); 

 
public interface IEnumerable<out T> : IEnumerable 

    IEnumerator<T> GetEnumerator(); 

 
public interface IEnumerator<out T> : IDisposable, IEnumerator 

    T Current { get; } 

一、C#1實現迭代方式
C#1通過實現接口實現迭代,下面是一個例子,可以指定起始的順序來迭代集合,其中的一些注意點在注釋中有所體現。
[csharp] 
public class IterationSample : IEnumerable<string> 
    { 
        string[] values; 
        int startingPoint; 
 
        public IterationSample(string[] values, int startingPoint) 
        { 
            this.values = values; 
            this.startingPoint = startingPoint; 
        } 
        public IEnumerator<string> GetEnumerator() 
        { 
            // This is important to return a new instance of iterator 
            // so that each foreach loop will have its own iterator. 
            return new IterationSampleIterator(this);  
        } 
 
        // Class that implement IEnumerable<T> must also implement IEnumerable,  
        // here is a workaround to implement GetEnumerator method that defined  
        // in both IEnumerable<T> and IEnumerable.  
        IEnumerator IEnumerable.GetEnumerator() 
        { 
            return GetEnumerator();  
        } 
 
        // Inner class can access to private members of its parent class.  
        class IterationSampleIterator : IEnumerator<string> 
        { 
            IterationSample parent; 
            int position; 
 
            internal IterationSampleIterator(IterationSample parent) 
            { 
                this.parent = parent; 
                position = -1; 
            } 
 
            public bool MoveNext() 
            { 
                if (position != parent.values.Length) 
                { 
                    position++; 
                } 
 
                return position < parent.values.Length; 
            } 
 
            object IEnumerator.Current 
            { 
                get { return Current; } 
            } 
 
            public string Current 
            { 
                get 
                { 
                    if (position == -1 || 
                    position == parent.values.Length) 
                    { 
                        throw new InvalidOperationException(); 
                    } 
                    int index = position + parent.startingPoint; 
                    index = index % parent.values.Length; 
                    return parent.values[index]; 
                } 
            } 
 
            public void Reset() 
            { 
                position = -1; 
            } 
 
            public void Dispose() 
            { 
            } 
        } 
    } 
 
    string[] values = { "a", "b", "c", "d", "e" }; 
    IterationSample collection = new IterationSample(values, 3); 
    foreach (object x in collection) 
    { 
        Console.WriteLine(x); 
    } 

二、C#2實現迭代方式
C#2提供了yield關鍵字,使得迭代實現代碼大大簡化,下面使用yield方式來改寫上面的實現。
[csharp]
public class IterationSample : IEnumerable<string> 

    string[] values; 
    int startingPoint; 
 
    public IterationSample(string[] values, int startingPoint) 
    { 
        this.values = values; 
        this.startingPoint = startingPoint; 
    } 
    public IEnumerator<string> GetEnumerator() 
    { 
        for (int index = 0; index < values.Length; index++) 
        { 
            yield return values[(index + startingPoint) % values.Length]; 
        } 
    } 
 
    // Class that implement IEnumerable<T> must also implement IEnumerable,  
    // here is a workaround to implement GetEnumerator method that defined  
    // in both IEnumerable<T> and IEnumerable.  
    IEnumerator IEnumerable.GetEnumerator() 
    { 
        return GetEnumerator();  
    } 

 
string[] values = { "a", "b", "c", "d", "e" }; 
IterationSample collection = new IterationSample(values, 3); 
foreach (object x in collection) 
{ www.2cto.com
    Console.WriteLine(x); 

yield 關鍵字向編譯器指示它所在的方法是迭代器塊。 編譯器生成一個類來實現迭代器塊中表示的行為。 在迭代器塊中,yield 關鍵字與 return 關鍵字結合使用,向枚舉器對象提供值。 這是一個返回值,例如,在 foreach 語句的每一次循環中返回的值。 yield 關鍵字也可與 break 結合使用,表示迭代結束。
[csharp] 
yield return <expression>; 
yield break; 

三、迭代器
迭代器是 C# 2.0 中的新功能。迭代器是方法、get 訪問器或運算符,它使您能夠在類或結構中支持 foreach 迭代,而不必實現整個 IEnumerable 接口。您只需提供一個迭代器,即可遍歷類中的數據結構。當編譯器檢測到迭代器時,它將自動生成 IEnumerable 或 IEnumerable<T> 接口的相關迭代方法,進一步簡化了迭代的開發。
[csharp] 
public class Program 

    //using System.Collections; 
    public static IEnumerable Power(int number, int exponent) 
    { 
        int counter = 0; 
        int result = 1; 
        while (counter++ < exponent) 
        { 
            result = result * number; 
            yield return result; 
        } 
    } 
 
    static void Main() 
    { 
        // Display powers of 2 up to the exponent 8: 
        foreach (int i in Power(2, 8)) 
        { 
            Console.Write("{0} ", i); 
        } 
    } 

/*
Output:
2 4 8 16 32 64 128 256 
*/ 

四、迭代器實現LINQ查詢
下面的例子使用迭代器實現了LINQ查詢中Where方法。
[csharp] 
public static IEnumerable<T> Where<T>(IEnumerable<T> source, 
Predicate<T> predicate) 

if (source == null || predicate == null) 

throw new ArgumentNullException(); 

return WhereImpl(source, predicate); 

private static IEnumerable<T> WhereImpl<T>(IEnumerable<T> source, 
Predicate<T> predicate) 

foreach (T item in source) 

if (predicate(item)) 

yield return item; 



... 
IEnumerable<string> lines = LineReader.ReadLines("../../FakeLinq.cs"); 
Predicate<string> predicate = delegate(string line) 
{ return line.StartsWith("using"); }; 
foreach (string line in Where(lines, predicate)) 

Console.WriteLine(line); 

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