C#デザインパターン  - Iterator

ここに掲載したコードは、『増補改訂版Java言語で学ぶデザインパターン入門 / 結城 浩(著)』に掲載されているサンプルコードをC#に移植したものです。
解説らしい解説は載せていませんので、『増補改訂版Java言語で学ぶデザインパターン入門 / 結城 浩(著)』も合わせてお読みください。

※当ソースは、Visual C# 2008 Express Editionで動作を確認しています。
  Visual Studio 2005をお使いの方は、ブログの記事を残しておきますので、そちらをご覧ください。



■Book.cs
using System;

namespace Gushwell.Design.Patterns {
    public class Book {
        private string name;

        public Book(System.String name) {
            this.name = name;
        }

        public string Name {
            get { return name; }
        }
    }
}




■BookShelf.cs
using System;
using System.Collections.Generic;

namespace Gushwell.Design.Patterns {
    // IEnumerable<T>を実装するのがC#流
    // でも、この程度ならば、List<Book>だけでOKだと思う。
    public class BookShelf : IEnumerable<Book> {
        private Book[] books;
        private int last = 0;

        public BookShelf(int maxsize) {
            this.books = new Book[maxsize];
        }

        public virtual int Length {
            get { return last; }
        }

        public virtual Book this[int index] {
            get { return books[index]; }
        }

        public virtual void AppendBook(Book book) {
            this.books[last] = book;
            last++;
        }

        public virtual IEnumerator<Book> GetEnumerator() {
            for (int i = 0; i < Length; i++) {
                yield return this[i];
            }
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
            return this.GetEnumerator();
        }
    }
}





■Program.cs
using System;
using System.Linq;
using Gushwell.Dejavu;

namespace Gushwell.Design.Patterns {
    public class Program {
        [STAThread]
        public static void Main(System.String[] args) {
            BookShelf bookShelf = new BookShelf(4);
            bookShelf.AppendBook(new Book("Around the World in 80 Days"));
            bookShelf.AppendBook(new Book("Bible"));
            bookShelf.AppendBook(new Book("Cinderella"));
            bookShelf.AppendBook(new Book("Daddy-Long-Legs"));

            // 書き方1:foreach文が使える
            foreach (Book b in bookShelf) {
                Console.WriteLine(b.Name);
            }
            Console.WriteLine();

            // 書き方2:拡張メソッドとの組み合わせで、こんな書き方もOK
            bookShelf.ForEach(b => Console.WriteLine(b.Name));
            Console.WriteLine();

            // 書き方3: MoveNextとCurrentで順に取り出す。
            var ite = bookShelf.GetEnumerator();
            Book book = null;
            while (ite.MoveNext()) {
                book = ite.Current;
                Console.WriteLine(book.Name);
            }
            ite.Dispose();
            Console.WriteLine();

            // 書き方4:配列としてアクセス
            for (int i = 0; i < bookShelf.Length; i++) {
                Console.WriteLine(bookShelf[i].Name);
            }
        }
    }
}





■EnumerableExtentions.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Gushwell.Dejavu {
    public static class EnumerableExtentions {
        public static void ForEach<T>(this IEnumerable<T> source, Action<T> action) {
            foreach (var x in source) {
                action(x);
            }
        }

        public static void ForEach<T>(this IEnumerable<T> source, Action<T, int> func) {
            int i = 0;
            foreach (var x in source) {
                func(x, i);
                i++;
            }
        }
    }
}