• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            Onway

            我是一只菜菜菜菜鳥...
            posts - 61, comments - 56, trackbacks - 0, articles - 34

            可枚舉對象與枚舉器

            Posted on 2015-08-01 14:00 Onway 閱讀(610) 評論(1)  編輯 收藏 引用 所屬分類: 使用說明
            1,最先學會的是,繼承了IEnumerable接口的類都可以使用foreach遍歷,但一直沒有多想。

            2,IEnumerable和IEnumerable<out T>的定義:
                public interface IEnumerable
                {
                    IEnumerator GetEnumerator();
                }

                public interface IEnumerable<out T> : IEnumerable
                {
                    IEnumerator<T> GetEnumerator();
                }

            3,IEnumerator和IEnumerator<out T>的定義:
                public interface IEnumerator
                {
                    object Current { get; }
                    bool MoveNext();
                    void Reset();
                }

                public interface IEnumerator<out T> : IDisposable, IEnumerator
                {
                    T Current { get; }
                }

            4,可以這么理解兩個接口:可枚舉對象返回一個枚舉器用于枚舉其內部狀態。

            5,每一次foreach之后,都會重新調用GetEnumerator,foreach語句并不會調用Enumerator的Reset方法;
            對于泛型版本的GetEnumerator<T>,foreach同樣不會調用Reset方法,但會調用Dispose。
            以下是測試代碼的輸出:
            [08.177] StringEnumerator
            [08.191] StringMoveNext
            [08.191] StringCurrent
            Hello
            [08.191] StringMoveNext
            [08.191] StringCurrent
            World
            [08.191] StringMoveNext
            [08.191] StringCurrent
            !
            [08.192] StringMoveNext
            [08.192] StringEnumerator
            [08.192] StringMoveNext
            [08.192] StringCurrent
            Hello
            [08.192] StringMoveNext
            [08.192] StringCurrent
            World
            [08.193] StringMoveNext
            [08.193] StringCurrent
            !
            [08.193] StringMoveNext
            [08.195] NumberEnumerator
            [08.196] NumberMoveNext
            [08.196] NumberCurrent<T>
            1
            [08.198] NumberMoveNext
            [08.199] NumberCurrent<T>
            2
            [08.199] NumberMoveNext
            [08.201] NumberDispose
            [08.201] NumberEnumerator
            [08.201] NumberMoveNext
            [08.202] NumberCurrent<T>
            1
            [08.202] NumberMoveNext
            [08.203] NumberCurrent<T>
            2
            [08.203] NumberMoveNext
            [08.203] NumberDispose

            using System;
            using System.Collections;
            using System.Collections.Generic;

            namespace ConsoleTest
            {
                public class Program
                {
                    static void Main(string[] args)
                    {
                        StringEnumerable se = new StringEnumerable(); 
                        foreach (string s in se)
                        {
                            Console.WriteLine(s);
                        }
                        foreach (string s in se)
                        {
                            Console.WriteLine(s);
                        }
                        Console.WriteLine();

                        NumberEnumerable<double> ne = new NumberEnumerable<double>(new double[] { 1.0, 2.0 });
                        foreach (double d in ne)
                        {
                            Console.WriteLine(d);
                        }
                        foreach (double d in ne)
                        {
                            Console.WriteLine(d);
                        }
                        Console.ReadKey();
                    }
                }

                class StringEnumerable : IEnumerable
                {
                    private string[] strs = new string[] { "Hello", "World", "!" };

                    public IEnumerator GetEnumerator()
                    {
                        return new StringEnumerator(strs);
                    }
                }

                class StringEnumerator : IEnumerator
                {
                    private string[] strs;
                    private int index;
                    private object current;

                    public StringEnumerator(string[] strs)
                    {
                        Console.WriteLine("[{0}] StringEnumerator", DateTime.Now.ToString("ss.fff"));
                        this.strs = strs;
                        index = -1;
                    }

                    public object Current
                    {
                        get
                        {
                            Console.WriteLine("[{0}] StringCurrent", DateTime.Now.ToString("ss.fff"));
                            return current;
                        }
                    }

                    public bool MoveNext()
                    {
                        Console.WriteLine("[{0}] StringMoveNext", DateTime.Now.ToString("ss.fff"));
                        while (++index < strs.Length)
                        {
                            current = strs[index];
                            return true;
                        }
                        return false;
                    }

                    public void Reset()
                    {
                        Console.WriteLine("[{0}] StringReset", DateTime.Now.ToString("ss.fff"));
                        index = -1;
                    }
                }

                class NumberEnumerable<T> : IEnumerable<T>
                {
                    private T[] ts;

                    public NumberEnumerable(T[] ts)
                    {
                        this.ts = ts;
                    }

                    IEnumerator IEnumerable.GetEnumerator()
                    {
                        return new NumberEnumerator<T>(ts);
                    }

                    IEnumerator<T> IEnumerable<T>.GetEnumerator()
                    {
                        return new NumberEnumerator<T>(ts);
                    }
                }

                class NumberEnumerator<T> : IEnumerator<T>
                {
                    private T[] strs;
                    private int index;
                    private T current;

                    public NumberEnumerator(T[] strs)
                    {
                        Console.WriteLine("[{0}] NumberEnumerator", DateTime.Now.ToString("ss.fff"));
                        this.strs = strs;
                        index = -1;
                    }

                    object IEnumerator.Current
                    {
                        get
                        {
                            Console.WriteLine("[{0}] NumberCurrent", DateTime.Now.ToString("ss.fff"));
                            return current;
                        }
                    }

                    T IEnumerator<T>.Current
                    {
                        get
                        {
                            Console.WriteLine("[{0}] NumberCurrent<T>", DateTime.Now.ToString("ss.fff"));
                            return current;
                        }
                    }

                    public bool MoveNext()
                    {
                        Console.WriteLine("[{0}] NumberMoveNext", DateTime.Now.ToString("ss.fff"));
                        while (++index < strs.Length)
                        {
                            current = strs[index];
                            return true;
                        }
                        return false;
                    }

                    public void Reset()
                    {
                        Console.WriteLine("[{0}] NumberReset", DateTime.Now.ToString("ss.fff"));
                        index = -1;
                    }

                    public void Dispose()
                    {
                        Console.WriteLine("[{0}] NumberDispose", DateTime.Now.ToString("ss.fff"));
                        index = -1;
                    }
                }
            }

            6
            ,foreach默認可枚舉對象的GetEnumerator方法,其他需要進行枚舉的方法需要返回IEnumerable或者IEnumerable<T>,以供foreach調用其GetEnumerator方法。

            7,yield語句只能使用在返回IEnumerable或者IEnumerator接口的方法中。
            yield語句會被編譯為實現了IEnumerator<T>的內部枚舉器。
            以下是代碼使用.NET Reflector 7.0反編譯出來的結果:
            using System;
            using System.Collections;
            using System.Collections.Generic;

            namespace YieldTest
            {
                class Program
                {
                    static void Main(string[] args)
                    {
                        YieldString ys = new YieldString();
                        foreach (string s in ys)
                        {
                            Console.WriteLine(s);
                        }
                        foreach (string s in ys.Next())
                        {
                            Console.WriteLine(s);
                        }
                        Console.ReadKey();
                    }
                }

                class YieldString
                {
                    private string[] strs = new string[] { "Hello", "World", "!" };

                    public IEnumerator GetEnumerator()
                    {
                        foreach (string s in strs)
                        {
                            yield return s;
                        }
                    }

                    public IEnumerable Next()
                    {
                        foreach (string s in strs)
                        {
                            yield return s;
                        }
                    }
                }
            }

            internal class YieldString
            {
                // Fields
                private string[] strs = new string[] { "Hello", "World", "!" };

                // Methods
                public IEnumerator GetEnumerator()
                {
                    foreach (string iteratorVariable0 in this.strs)
                    {
                        yield return iteratorVariable0;
                    }
                }

                public IEnumerable Next()
                {
                    foreach (string iteratorVariable0 in this.strs)
                    {
                        yield return iteratorVariable0;
                    }
                }

                // Nested Types
                [CompilerGenerated]
                private sealed class <GetEnumerator>d__0 : IEnumerator<object>, IEnumerator, IDisposable
                {
                    // Fields
                    private int <>1__state;
                    private object <>2__current;
                    public YieldString <>4__this;
                    public string[] <>7__wrap3;
                    public int <>7__wrap4;
                    public string <s>5__1;

                    // Methods
                    [DebuggerHidden]
                    public <GetEnumerator>d__0(int <>1__state)
                    {
                        this.<>1__state = <>1__state;
                    }

                    private void <>m__Finally2()
                    {
                        this.<>1__state = -1;
                    }

                    private bool MoveNext()
                    {
                        try
                        {
                            switch (this.<>1__state)
                            {
                                case 0:
                                    this.<>1__state = -1;
                                    this.<>1__state = 1;
                                    this.<>7__wrap3 = this.<>4__this.strs;
                                    this.<>7__wrap4 = 0;
                                    while (this.<>7__wrap4 < this.<>7__wrap3.Length)
                                    {
                                        this.<s>5__1 = this.<>7__wrap3[this.<>7__wrap4];
                                        this.<>2__current = this.<s>5__1;
                                        this.<>1__state = 2;
                                        return true;
                                    Label_0079:
                                        this.<>1__state = 1;
                                        this.<>7__wrap4++;
                                    }
                                    this.<>m__Finally2();
                                    break;

                                case 2:
                                    goto Label_0079;
                            }
                            return false;
                        }
                        fault
                        {
                            this.System.IDisposable.Dispose();
                        }
                    }

                    [DebuggerHidden]
                    void IEnumerator.Reset()
                    {
                        throw new NotSupportedException();
                    }

                    void IDisposable.Dispose()
                    {
                        switch (this.<>1__state)
                        {
                            case 1:
                            case 2:
                                this.<>m__Finally2();
                                break;
                        }
                    }

                    // Properties
                    object IEnumerator<object>.Current
                    {
                        [DebuggerHidden]
                        get
                        {
                            return this.<>2__current;
                        }
                    }

                    object IEnumerator.Current
                    {
                        [DebuggerHidden]
                        get
                        {
                            return this.<>2__current;
                        }
                    }
                }

                [CompilerGenerated]
                private sealed class <Next>d__6 : IEnumerable<object>, IEnumerable, IEnumerator<object>, IEnumerator, IDisposable
                {
                    // Fields
                    private int <>1__state;
                    private object <>2__current;
                    public YieldString <>4__this;
                    public string[] <>7__wrap9;
                    public int <>7__wrapa;
                    private int <>l__initialThreadId;
                    public string <s>5__7;

                    // Methods
                    [DebuggerHidden]
                    public <Next>d__6(int <>1__state)
                    {
                        this.<>1__state = <>1__state;
                        this.<>l__initialThreadId = Thread.CurrentThread.ManagedThreadId;
                    }

                    private void <>m__Finally8()
                    {
                        this.<>1__state = -1;
                    }

                    private bool MoveNext()
                    {
                        try
                        {
                            switch (this.<>1__state)
                            {
                                case 0:
                                    this.<>1__state = -1;
                                    this.<>1__state = 1;
                                    this.<>7__wrap9 = this.<>4__this.strs;
                                    this.<>7__wrapa = 0;
                                    while (this.<>7__wrapa < this.<>7__wrap9.Length)
                                    {
                                        this.<s>5__7 = this.<>7__wrap9[this.<>7__wrapa];
                                        this.<>2__current = this.<s>5__7;
                                        this.<>1__state = 2;
                                        return true;
                                    Label_0079:
                                        this.<>1__state = 1;
                                        this.<>7__wrapa++;
                                    }
                                    this.<>m__Finally8();
                                    break;

                                case 2:
                                    goto Label_0079;
                            }
                            return false;
                        }
                        fault
                        {
                            this.System.IDisposable.Dispose();
                        }
                    }

                    [DebuggerHidden]
                    IEnumerator<object> IEnumerable<object>.GetEnumerator()
                    {
                        if ((Thread.CurrentThread.ManagedThreadId == this.<>l__initialThreadId) && (this.<>1__state == -2))
                        {
                            this.<>1__state = 0;
                            return this;
                        }
                        return new YieldString.<Next>d__6(0) { <>4__this = this.<>4__this };
                    }

                    [DebuggerHidden]
                    IEnumerator IEnumerable.GetEnumerator()
                    {
                        return this.System.Collections.Generic.IEnumerable<System.Object>.GetEnumerator();
                    }

                    [DebuggerHidden]
                    void IEnumerator.Reset()
                    {
                        throw new NotSupportedException();
                    }

                    void IDisposable.Dispose()
                    {
                        switch (this.<>1__state)
                        {
                            case 1:
                            case 2:
                                this.<>m__Finally8();
                                break;
                        }
                    }

                    // Properties
                    object IEnumerator<object>.Current
                    {
                        [DebuggerHidden]
                        get
                        {
                            return this.<>2__current;
                        }
                    }

                    object IEnumerator.Current
                    {
                        [DebuggerHidden]
                        get
                        {
                            return this.<>2__current;
                        }
                    }
                }
            }

            Feedback

            # re: 可枚舉對象與枚舉器  回復  更多評論   

            2015-08-01 14:28 by Onway
            為什么反編譯出來的MoveNext方法是private級別的呢?
            香蕉aa三级久久毛片| 91久久精品91久久性色| 国产精品伊人久久伊人电影 | 日韩中文久久| 久久久久波多野结衣高潮| 一本一道久久综合狠狠老| 久久久久久久尹人综合网亚洲| 久久久久国产一级毛片高清板| 日韩精品久久无码中文字幕| 国产精品久久久久久久久久免费| 亚洲中文字幕无码久久2020 | 亚洲一级Av无码毛片久久精品| 无码人妻久久久一区二区三区 | 久久婷婷五月综合色奶水99啪| 69久久夜色精品国产69| 一本久久综合亚洲鲁鲁五月天亚洲欧美一区二区 | 国产成人精品久久亚洲高清不卡 | 中文国产成人精品久久亚洲精品AⅤ无码精品 | 久久精品国产亚洲AV无码麻豆| 日韩电影久久久被窝网| 亚洲综合精品香蕉久久网97| 久久国产免费直播| 一本久久免费视频| 久久精品国产99国产精品| 9久久9久久精品| 精品久久久久久亚洲精品| 亚洲精品无码久久千人斩| 亚洲精品国产自在久久| 久久久久一本毛久久久| 成人a毛片久久免费播放| 久久青青草原国产精品免费 | 久久一区二区免费播放| 久久精品成人欧美大片| 久久久WWW免费人成精品| 久久久国产精华液| 久久久久久av无码免费看大片| 四虎国产精品免费久久5151 | 亚洲&#228;v永久无码精品天堂久久 | 久久精品黄AA片一区二区三区| 日韩人妻无码精品久久久不卡| 久久久久亚洲Av无码专|