C#のコードによる問題


次のコードを参照してください.
static void Main(string[] args)
        {
            Person[] persons = new Person[]
                                   {
                                       new Person{FirstName="aaa",LastName="bbb"},
                                       new Person{FirstName="ccc",LastName="ddd"},
                                       new Person{FirstName="eee",LastName="fff"}
                                   };
            People people = new People(persons);

            foreach (var item in people )
            {
                Console.WriteLine(item);
            }
        }

以上のコードに基づいてPersonクラスとPeopleクラスを宣言しますが、実はこのコードは反復器をテストして、まず反復器とは何かを見てみましょう.
  • 反復器は、同じタイプの秩序化されたシーケンスを返すコードです.
  • 反復器は、メソッド、属性、演算子のコード体として使用できます.
  • 反復器はyield returnを使用して各要素とyield breakを返して反復を終了します.
  • は、クラス内で複数の反復器を実装することができる.
  • 反復器の戻りタイプは、IEnumerable、IEnumerator、IEnumerableまたはIEnumeratorである必要があります.

  • IEnumerableインタフェース


    非汎用集合での単純な反復をサポートする列挙器が開示される.
    公開メンバー:
    GetEnumerator
    ループ・アクセス・セットの列挙数を返します.

    IEnumeratorインタフェース


    非汎用集合の単純な反復をサポートします.IEnumeratorは、すべての非汎用列挙数のベースインタフェースである.
    次のコードはIEnumerableインタフェースとIEnumeratorインタフェースを実現します.
    using System;
    using System.Collections;
    
    public class Person
    {
        public Person(string fName, string lName)
        {
            this.firstName = fName;
            this.lastName = lName;
        }
    
        public string firstName;
        public string lastName;
    }
    
    public class People : IEnumerable
    {
        private Person[] _people;
        public People(Person[] pArray)
        {
            _people = new Person[pArray.Length];
    
            for (int i = 0; i < pArray.Length; i++)
            {
                _people[i] = pArray[i];
            }
        }
    
        public IEnumerator GetEnumerator()
        {
            return new PeopleEnum(_people);
        }
    }
    
    public class PeopleEnum : IEnumerator
    {
        public Person[] _people;
    
        // Enumerators are positioned before the first element
        // until the first MoveNext() call.
        int position = -1;
    
        public PeopleEnum(Person[] list)
        {
            _people = list;
        }
    
        public bool MoveNext()
        {
            position++;
            return (position < _people.Length);
        }
    
        public void Reset()
        {
            position = -1;
        }
    
        public object Current
        {
            get
            {
                try
                {
                    return _people[position];
                }
                catch (IndexOutOfRangeException)
                {
                    throw new InvalidOperationException();
                }
            }
        }
    }
    
    class App
    {
        static void Main()
        {
            Person[] peopleArray = new Person[3]
            {
                new Person("John", "Smith"),
                new Person("Jim", "Johnson"),
                new Person("Sue", "Rabon"),
            };
    
            People peopleList = new People(peopleArray);
            foreach (Person p in peopleList)
                Console.WriteLine(p.firstName + " " + p.lastName);
    
        }
    }

    IEnumerator汎用インタフェースとIEnumerable汎用インタフェース


    汎用コレクションでの単純な反復をサポートします.
    //Type parameter T in angle brackets.
    public class GenericList<T> : System.Collections.Generic.IEnumerable<T>
    {
        protected Node head;
        protected Node current = null;
    
        // Nested class is also generic on T
        protected class Node
        {
            public Node next;
            private T data;  //T as private member datatype
    
            public Node(T t)  //T used in non-generic constructor
            {
                next = null;
                data = t;
            }
    
            public Node Next
            {
                get { return next; }
                set { next = value; }
            }
    
            public T Data  //T as return type of property
            {
                get { return data; }
                set { data = value; }
            }
        }
    
        public GenericList()  //constructor
        {
            head = null;
        }
    
        public void AddHead(T t)  //T as method parameter type
        {
            Node n = new Node(t);
            n.Next = head;
            head = n;
        }
    
        // Implementation of the iterator
        public System.Collections.Generic.IEnumerator<T> GetEnumerator()
        {
            Node current = head;
            while (current != null)
            {
                yield return current.Data;
                current = current.Next;
            }
        }
    
        // IEnumerable<T> inherits from IEnumerable, therefore this class 
        // must implement both the generic and non-generic versions of 
        // GetEnumerator. In most cases, the non-generic method can 
        // simply call the generic method.
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
    
    public class SortedList<T> : GenericList<T> where T : System.IComparable<T>
    {
        // A simple, unoptimized sort algorithm that 
        // orders list elements from lowest to highest:
    
        public void BubbleSort()
        {
            if (null == head || null == head.Next)
            {
                return;
            }
            bool swapped;
    
            do
            {
                Node previous = null;
                Node current = head;
                swapped = false;
    
                while (current.next != null)
                {
                    //  Because we need to call this method, the SortedList
                    //  class is constrained on IEnumerable<T>
                    if (current.Data.CompareTo(current.next.Data) > 0)
                    {
                        Node tmp = current.next;
                        current.next = current.next.next;
                        tmp.next = current;
    
                        if (previous == null)
                        {
                            head = tmp;
                        }
                        else
                        {
                            previous.next = tmp;
                        }
                        previous = tmp;
                        swapped = true;
                    }
                    else
                    {
                        previous = current;
                        current = current.next;
                    }
                }
            } while (swapped);
        }
    }
    
    // A simple class that implements IComparable<T> using itself as the 
    // type argument. This is a common design pattern in objects that 
    // are stored in generic lists.
    public class Person : System.IComparable<Person>
    {
        string name;
        int age;
    
        public Person(string s, int i)
        {
            name = s;
            age = i;
        }
    
        // This will cause list elements to be sorted on age values.
        public int CompareTo(Person p)
        {
            return age - p.age;
        }
    
        public override string ToString()
        {
            return name + ":" + age;
        }
    
        // Must implement Equals.
        public bool Equals(Person p)
        {
            return (this.age == p.age);
        }
    }
    
    class Program
    {
        static void Main()
        {
            //Declare and instantiate a new generic SortedList class.
            //Person is the type argument.
            SortedList<Person> list = new SortedList<Person>();
    
            //Create name and age values to initialize Person objects.
            string[] names = new string[] 
            { 
                "Franscoise", 
                "Bill", 
                "Li", 
                "Sandra", 
                "Gunnar", 
                "Alok", 
                "Hiroyuki", 
                "Maria", 
                "Alessandro", 
                "Raul" 
            };
    
            int[] ages = new int[] { 45, 19, 28, 23, 18, 9, 108, 72, 30, 35 };
    
            //Populate the list.
            for (int x = 0; x < 10; x++)
            {
                list.AddHead(new Person(names[x], ages[x]));
            }
    
            //Print out unsorted list.
            foreach (Person p in list)
            {
                System.Console.WriteLine(p.ToString());
            }
            System.Console.WriteLine("Done with unsorted list");
    
            //Sort the list.
            list.BubbleSort();
    
            //Print out sorted list.
            foreach (Person p in list)
            {
                System.Console.WriteLine(p.ToString());
            }
            System.Console.WriteLine("Done with sorted list");
        }
    }

    PersonクラスとPeopleクラスを定義できます
    public  class Person
            {
                public string FirstName { get; set; }
                public string LastName { get; set; }
    
                public override string ToString()
                {
                    return FirstName + LastName;
                }
            }
      public class People :IEnumerable
            {
                private Person[] _persons;
    
                public People(Person[] persons)
                {
                    _persons = new Person[persons.Length];
                    for(int i = 0; i<persons.Length;i++)
                    {
                        _persons[i] = persons[i];
                    }
                }
    
                public IEnumerator GetEnumerator()
                {
                    for(int i = 0; i<_persons.Length;i++)
                    {
                        yield return _persons[i];
                    }
                }
            }