2016-08-22 5 views
-2

私は複合パターンの後にオブジェクトの集合を持っています。それらはIEnumeratorで横断したいツリー構造を形成します。私は本の "Head First Design Patterns"のJavaコードを翻訳しています。私はIEnumeratorインターフェイスを実装する2つのクラスを実装しました:CompositeIteratorおよびNullIterator合成パターンにIEnumerator <T>インターフェイスを実装する方法は?

Thisは、私がC#に翻訳したいJavaコードです。

はまた、これは私の私が唯一MoveNextメソッドを(呼び出す必要がありwanted implementation of the Waitress class、)全体のツリー構造を横断する現在のです。

私のコードは、イテレータを含むwhileループには入っておらず、ベジタリアンMenuItemオブジェクトをコンソールに出力したいと思います。

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

namespace Iterator 
{ 
    class Program 
    { 
    static void Main(string[] args) 
    { 
     MenuComponent pancakeHouseMenu = new Menu("PANCAKEHOUSE MENU", "Breakfast"); 
     MenuComponent dinerMenu = new Menu("DINER MENU", "Lunch"); 
     MenuComponent cafeMenu = new Menu("CAFE MENU", "Dinner"); 
     MenuComponent dessertMenu = new Menu("DESSERT MENU", "Dessert of course!"); 

     MenuComponent allMenus = new Menu("ALL MENUS", "All menus combined"); 

     allMenus.Add(pancakeHouseMenu); 
     allMenus.Add(dinerMenu); 
     allMenus.Add(cafeMenu); 

     pancakeHouseMenu.Add(new MenuItem("K&B Pancake breakfast", "pancakes with scrambled eggs, and toast", true, 2.99)); 
     pancakeHouseMenu.Add(new MenuItem("Regular Pancake breakfast", "pancakes with fried eggs, sausage", false, 2.99)); 

     dinerMenu.Add(new MenuItem("Veggie burguer and air fries", "Veggie burguer on a whole wheat bun, lettuce, tomato and fries", true, 3.99)); 
     dinerMenu.Add(new MenuItem("Soup of the day", "Soup of the day with a side salad", false, 3.69)); 

     dinerMenu.Add(dessertMenu); 

     dessertMenu.Add(new MenuItem("Apple pie", "Apple pie with a flakey crust, topped with vanilla ice cream", true, 1.59)); 

     cafeMenu.Add(new MenuItem("Vegetarian BLT", "(Fakin') Bacon with lettuce & tomato on whole wheat", true, 2.99)); 
     cafeMenu.Add(new MenuItem("BLT", "Bacon with lettuce & tomato on whole wheat", false, 2.99)); 

     Waitress waitress = new Waitress(allMenus); 
     waitress.PrintVegetarianMenu(); 
    } 
    } 

    class Waitress 
    { 
    private MenuComponent AllMenus { get; set; } 

    public Waitress(MenuComponent allMenus) 
    { 
     AllMenus = allMenus; 
    } 

    public void PrintMenu() 
    { 
     AllMenus.Print(); 
    } 

    public void PrintVegetarianMenu() 
    { 
     CompositeIterator<MenuComponent> iterator = (CompositeIterator<MenuComponent>)AllMenus.CreateIterator(); 
     Console.WriteLine("VEGATARIAN MENU"); 

     // this loop is never entered 
     while (iterator.MoveNext()) 
     { 
     Console.WriteLine("inside while loop"); 
     MenuComponent menuComponent = (MenuComponent)iterator.Current; 
     Console.WriteLine(menuComponent.Name); 

     try 
     { 
      if (menuComponent.Vegetarian) 
      { 
      menuComponent.Print(); 
      } 
     } 
     catch (NotSupportedException e) 
     { 
      Console.WriteLine("Operation not supported."); 
     } 
     } 
    } 
    } 

    /* 
    Methods of MenuComponent class are virtual, because we sometimes want to use the default behavior. The CreateIterator method is abstract. 
    */ 
    abstract class MenuComponent 
    { 
    // Composite methods 
    public virtual void Add(MenuComponent menuComponent) 
    { 
     throw new NotSupportedException(); 
    } 

    public virtual void Remove(MenuComponent menuComponent) 
    { 
     throw new NotSupportedException(); 
    } 

    public virtual MenuComponent GetChild(int i) 
    { 
     throw new NotSupportedException(); 
    } 
    // End of composite methods 

    // Operation methods 
    public virtual string Name 
    { 
     get 
     { 
     throw new NotSupportedException();   
     } 
     set 
     { 
     throw new NotSupportedException(); 
     } 
    } 

    public virtual string Description 
    { 
     get 
     { 
     throw new NotSupportedException();   
     } 
     set 
     { 
     throw new NotSupportedException(); 
     } 
    } 

    public virtual bool Vegetarian 
    { 
     get 
     { 
     throw new NotSupportedException();   
     } 
     set 
     { 
     throw new NotSupportedException(); 
     } 
    } 

    public virtual double Price 
    { 
     get 
     { 
     throw new NotSupportedException(); 
     } 
     set 
     { 
     throw new NotSupportedException(); 
     } 
    } 

    public virtual void Print() 
    { 
     throw new NotSupportedException(); 
    } 
    // End of operation methods 

    public abstract IEnumerator CreateIterator(); 
    } 

    public sealed class CompositeIterator<T> : IEnumerator<T> { 
    private readonly Stack<IEnumerator<T>> Stack = new Stack<IEnumerator<T>>(); 

    public CompositeIterator(IEnumerator<T> initial) 
    { 
     Stack.Push(initial); 
    } 

    public bool MoveNext() 
    { 
     while (Stack.Any()) 
     { 
     if (!Stack.Peek().MoveNext()) 
     { 
      Stack.Pop().Dispose(); 
      continue; 
     } 
     var tmp = Current as IEnumerable<T>; 
     if (tmp != null) { Stack.Push(tmp.GetEnumerator()); } 
     } 
     return false; 
    } 

    public void Reset() { throw new NotSupportedException(); } 

    public T Current => Stack.Peek() != null ? Stack.Peek().Current : default(T); 

    object IEnumerator.Current => Current; 

    public void Dispose() 
    { 
     if (!Stack.Any()) { return; } 
     try { 
     foreach (var x in Stack) { 
      x.Dispose(); 
     } 
     } catch { } 
    } 
    } 

    public sealed class NullIterator<T> : IEnumerator<T> { 
    public NullIterator() {} 

    public bool MoveNext() 
    { 
     return false; 
    } 

    public void Reset() { throw new NotSupportedException(); } 

    public T Current 
    { 
     get 
     { 
     return default(T); 
     } 
    } 

    object IEnumerator.Current => Current; 

    public void Dispose() 
    { 
     return; 
    } 
    } 

    // This is a tree leaf 
    class MenuItem : MenuComponent 
    { 
    public override string Name { get; set; } 
    public override string Description { get; set; } 
    public override bool Vegetarian { get; set; } 
    public override double Price { get; set; } 

    public MenuItem(string name, string description, bool vegetarian, double price) 
    { 
     Name = name; 
     Description = description; 
     Vegetarian = vegetarian; 
     Price = price; 
    } 

    public override void Print() 
    { 
     Console.Write(" " + Name); 
     if (Vegetarian) 
     { 
     Console.Write("(v)"); 
     } 
     Console.Write(", " + Price); 
     Console.Write("  -- " + Description); 
    } 

    public override IEnumerator CreateIterator() 
    { 
     return new NullIterator<MenuItem>(); 
    } 
    } 

    // This is a tree node 
    class Menu : MenuComponent 
    { 
    public List<MenuComponent> MenuComponents; 
    public override string Name { get; set; } 
    public override string Description { get; set; } 

    public Menu(string name, string description) 
    { 
     Name = name; 
     Description = description; 
     MenuComponents = new List<MenuComponent>(); 
    } 

    public override void Add(MenuComponent menuComponent) 
    { 
     MenuComponents.Add(menuComponent); 
    } 

    public override void Remove(MenuComponent menuComponent) 
    { 
     MenuComponents.Remove(menuComponent); 
    } 

    public override MenuComponent GetChild(int i) 
    { 
     return MenuComponents[i]; 
    } 

    // we have to use recursion to print all the hierarchy 
    public override void Print() 
    { 
     Console.Write("\n" + Name); 
     Console.WriteLine(", " + Description); 
     Console.WriteLine("--------------"); 

     IEnumerator iterator = MenuComponents.GetEnumerator(); 

     while(iterator.MoveNext()) 
     { 
     MenuComponent menuComponent = (MenuComponent)iterator.Current; 
     menuComponent.Print(); 
     Console.Write("\n"); 
     } 
    } 

    public override IEnumerator CreateIterator() 
    { 
     return new CompositeIterator<MenuComponent>(MenuComponents.GetEnumerator()); 
    } 
    } 
} 
+2

あなたのコードはどこにでも 'IEnumerable'言及していない - あなたは* *現時点ではそれを実装しようとしていません。次に、あなたは 'IEnumerator .Current'を実装していません。コンパイラが不満を言っているので... –

+1

' IEnumerator 'ではなく、' IEnumerable 'が必要でしょうか? – Groo

+0

@Groo私はただ動作するものがほしいだけです。私はC#の初心者です。私はこの質問のタイトルを間違えました。 – freinn

答えて

0

は、C#のfreenodeのIRCチャンネルに人々を接触させた後、そのうちの一つは、私の本の中で1、私はここに来た答えよりもよりよい解決策を与えました。これは、コードであり、この答えを私は願って、私が何を望むか明確である:

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

namespace Iterator 
{ 
    class Program 
    { 
    static void Main(string[] args) 
    { 
     MenuComponent pancakeHouseMenu = new Menu("PANCAKEHOUSE MENU", "Breakfast"); 
     MenuComponent dinerMenu = new Menu("DINER MENU", "Lunch"); 
     MenuComponent cafeMenu = new Menu("CAFE MENU", "Dinner"); 
     MenuComponent dessertMenu = new Menu("DESSERT MENU", "Dessert of course!"); 

     MenuComponent allMenus = new Menu("ALL MENUS", "All menus combined"); 

     allMenus.Add(pancakeHouseMenu); 
     allMenus.Add(dinerMenu); 
     allMenus.Add(cafeMenu); 

     pancakeHouseMenu.Add(new MenuItem("K&B Pancake breakfast", "pancakes with scrambled eggs, and toast", true, 2.99)); 
     pancakeHouseMenu.Add(new MenuItem("Regular Pancake breakfast", "pancakes with fried eggs, sausage", false, 2.99)); 

     dinerMenu.Add(new MenuItem("Veggie burguer and air fries", "Veggie burguer on a whole wheat bun, lettuce, tomato and fries", true, 3.99)); 
     dinerMenu.Add(new MenuItem("Soup of the day", "Soup of the day with a side salad", false, 3.69)); 

     dinerMenu.Add(dessertMenu); 

     dessertMenu.Add(new MenuItem("Apple pie", "Apple pie with a flakey crust, topped with vanilla ice cream", true, 1.59)); 

     cafeMenu.Add(new MenuItem("Vegetarian BLT", "(Fakin') Bacon with lettuce & tomato on whole wheat", true, 2.99)); 
     cafeMenu.Add(new MenuItem("BLT", "Bacon with lettuce & tomato on whole wheat", false, 2.99)); 

     cafeMenu.Add(dessertMenu); 

     Waitress waitress = new Waitress(allMenus); 
     waitress.PrintVegetarianMenu(); 
    } 
    } 

    class Waitress 
    { 
    private MenuComponent AllMenus { get; set; } 

    public Waitress(MenuComponent allMenus) 
    { 
     AllMenus = allMenus; 
    } 

    public void PrintMenu() 
    { 
     AllMenus.Print(); 
    } 

    public void PrintVegetarianMenu() 
    { 
     Console.WriteLine("VEGATARIAN MENU"); 

     foreach (MenuComponent menuComponent in AllMenus) 
     { 
     try 
     { 
      if (menuComponent.Vegetarian) 
      { 
      menuComponent.Print(); 
      Console.Write("\n"); 
      } 
     } 
     catch (NotSupportedException) 
     { 
      Console.WriteLine("Operation not supported."); 
     } 
     } 
    } 
    } 

    abstract class MenuComponent : IEnumerable<MenuComponent> 
    { 
    // Composite methods 
    public abstract void Add(MenuComponent menuComponent); 

    public abstract void Remove(MenuComponent menuComponent); 

    public abstract MenuComponent GetChild(int i); 
    // End of composite methods 

    // Operation methods 
    public virtual string Name { get; set; } 

    public virtual string Description { get; set; } 

    public virtual bool Vegetarian { get; set; } 

    public virtual double Price { get; set; } 

    public abstract void Print(); 

    public abstract IEnumerator<MenuComponent> GetEnumerator(); 

    IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); 
    } 

    /// This is a tree leaf 
    class MenuItem : MenuComponent 
    { 
    public MenuItem(string name, string description, bool vegetarian, double price) 
    { 
     Name = name; 
     Description = description; 
     Vegetarian = vegetarian; 
     Price = price; 
    } 

    public override void Print() 
    { 
     Console.Write(" " + Name); 
     if (Vegetarian) 
     { 
     Console.Write("(v)"); 
     } 
     Console.Write(", " + Price); 
     Console.Write("  -- " + Description); 
    } 

    public override IEnumerator<MenuComponent> GetEnumerator() 
    { 
     yield break; 
    } 

    public override void Add(MenuComponent menuComponent) 
    { 
     throw new NotSupportedException(); 
    } 

    public override void Remove(MenuComponent menuComponent) 
    { 
     throw new NotSupportedException(); 
    } 

    public override MenuComponent GetChild(int i) 
    { 
     throw new NotSupportedException(); 
    } 
    } 

    /// This is a tree node 
    class Menu : MenuComponent 
    { 
    private List<MenuComponent> MenuComponents; 

    public Menu(string name, string description) 
    { 
     Name = name; 
     Description = description; 
     MenuComponents = new List<MenuComponent>(); 
    } 

    public override void Add(MenuComponent menuComponent) 
    { 
     MenuComponents.Add(menuComponent); 
    } 

    public override void Remove(MenuComponent menuComponent) 
    { 
     MenuComponents.Remove(menuComponent); 
    } 

    public override MenuComponent GetChild(int i) 
    { 
     return MenuComponents[i]; 
    } 

    // we have to use recursion to print all the hierarchy 
    public override void Print() 
    { 
     Console.Write("\n" + Name); 
     Console.WriteLine(", " + Description); 
     Console.WriteLine("--------------"); 

     foreach (MenuComponent menuComponent in MenuComponents) 
     { 
     menuComponent.Print(); 
     Console.Write("\n"); 
     } 
    } 

    public override IEnumerator<MenuComponent> GetEnumerator() 
    { 
     var components = new Stack<MenuComponent>(new[] { this }); 
     while (components.Any()) 
     { 
     MenuComponent component = components.Pop(); 
     yield return component; 
     var menu = component as Menu; 
     if (menu != null) 
     { 
      foreach (var n in menu.MenuComponents) components.Push(n); 
     } 
     } 
    } 
    } 
} 
0

これは、私はあなたが自分のイテレータを作成ずにが欲しいものを得るに来ることができる最も近い:

は、ここに私のコードです。私はdotnetフレームワークに既に存在するものを再コーディングする必要があるとは思わない。

class Program 
{ 
    static void Main(string[] args) 
    { 
     //var all = new Menu("ALL SECTIONS", "All menu sections"); 

     var pancakeHouseMenu = new Menu("PANCAKEHOUSE MENU", "Breakfast", 
      new MenuSection("PANCAKES", "Breakfast Pancakes Selection", 
       new MenuItem("K&B Pancake breakfast", "pancakes with scrambled eggs, and toast", true, 2.99m), 
       new MenuItem("Regular Pancake breakfast", "pancakes with fried eggs, sausage", false, 2.99m))); 

     var dinnerMenu = new Menu("DINNER MENU", "Lunch", 
      new MenuSection("","", 
       new MenuItem("Veggie burger and air fries", "Veggie burguer on a whole wheat bun, lettuce, tomato and fries", true, 3.99m), 
       new MenuItem("Soup of the day", "Soup of the day with a side salad", false, 3.69m))); 

     var cafeMenu = new Menu("CAFE MENU", "Dinner", 
      new MenuSection("", "", 
       new MenuItem("Vegetarian BLT", "(Fakin') Bacon with lettuce & tomato on whole wheat", true, 2.99m), 
       new MenuItem("BLT", "Bacon with lettuce & tomato on whole wheat", false, 2.99m)), 
      new MenuSection("DESSERT MENU", "Dessert of course!", 
       new MenuItem("Apple pie", "Apple pie with a flakey crust, topped with vanilla ice cream", true, 1.59m))); 

     var waiter = new Waitress(pancakeHouseMenu, dinnerMenu, cafeMenu); 

     //waiter.Print(); 
     //waiter.PrintVegenerian(); 


     WriteFileAndOpenNotepad(waiter.ToString()); 
     WriteFileAndOpenNotepad(waiter.ToVegetarianString()); 
    } 

    static void WriteFileAndOpenNotepad(string text) 
    { 
     var fn = Path.GetTempFileName(); 
     fn=Path.ChangeExtension(fn, ".txt"); 
     File.WriteAllText(fn, text); 
     Process.Start(fn); 
    } 
} 




public abstract class MenuComponent 
{ 
    public string Description { get; private set; } 
    public string Name { get; private set; } 
    protected MenuComponent(string name, string description) 
    { 
     this.Name=name; 
     this.Description=description; 
    } 

    public abstract override string ToString(); 
    public void Print() 
    { 
     Console.WriteLine(ToString()); 
    } 
} 
public class MenuItem : MenuComponent 
{ 
    public MenuItem(string name, string description, bool vegeterian, decimal price) 
     : base(name, description) 
    { 
     this.Price=price; 
     this.Vegetarian=vegeterian; 
    } 
    public decimal Price { get; set; } 
    public bool Vegetarian { get; set; } 

    public override string ToString() 
    { 
     //Use 28 columns for the item name 
     return string.Format("{0,28}{1}, {2}  -- {3}", 
      Name, Vegetarian ? "(v)" : " ", Price, Description); 
    } 

} 

public class MenuSection : MenuComponent 
{ 
    public MenuSection(string name, string description, params MenuItem[] items) 
     : this(name, description, items as IEnumerable<MenuItem>) 
    { } 

    public MenuSection(string name, string description, IEnumerable<MenuItem> items) : base(name, description) 
    { 
     this.Items=new List<MenuItem>(items); 
    } 

    public List<MenuItem> Items { get; private set; } 

    public override string ToString() 
    { 
     var sb = new StringBuilder(); 
     sb.AppendLine(); 
     if(Name.Length>0) 
     { 
      sb.AppendFormat("{0}, {1}", Name, Description); 
      sb.AppendLine(); 
      sb.AppendLine("--------------"); 
     } 
     foreach(var item in Items) 
     { 
      sb.AppendLine(); 
      sb.AppendLine(item.ToString()); 
     } 
     return sb.ToString(); 

    } 

    public MenuSection VegeterianSections 
    { 
     get 
     { 
      var veg = Items.Where((item) => item.Vegetarian); 
      return new MenuSection(Name, Description, veg); 
     } 
    } 
} 

public class Menu : MenuComponent 
{ 
    public Menu(string name, string description, IEnumerable<MenuSection> sections) 
     : base(name, description) 
    { 
     this.MenuSections=new List<MenuSection>(sections); 
    } 
    public Menu(string name, string description, params MenuSection[] sections) 
     : this(name, description, sections as IEnumerable<MenuSection>) 
    { } 

    public List<MenuSection> MenuSections { get; private set; } 

    public override string ToString() 
    { 
     var sb = new StringBuilder(); 
     sb.AppendLine(); 
     sb.AppendFormat("[{0}, {1}]", Name, Description); 
     sb.AppendLine(); 
     sb.AppendLine("=============="); 
     foreach(var section in MenuSections) 
     { 
      sb.AppendLine(); 
      sb.AppendLine(section.ToString()); 
     } 
     return sb.ToString(); 
    } 

    public Menu VegeraterianMenu 
    { 
     get 
     { 
      return new Menu(Name, Description, MenuSections.Select((section)=> section.VegeterianSections)); 
     } 
    } 
} 
public class Waitress 
{ 
    public Waitress(params Menu[] all) 
    { 
     this.AllMenus=new List<Menu>(all); 
     this.VegeratianMenu=all.Select((menu)=>menu.VegeraterianMenu).ToList(); 
    } 
    public IList<Menu> AllMenus { get; private set; } 
    public IList<Menu> VegeratianMenu { get; private set; } 

    public override string ToString() 
    { 
     StringBuilder sb = new StringBuilder(); 
     sb.AppendLine("*** A L L I T E M S ***"); 
     foreach(var item in AllMenus) 
     { 
      sb.AppendLine("************************"); 
      sb.AppendLine(item.ToString()); 
     } 
     return sb.ToString(); 
    } 

    public string ToVegetarianString() 
    { 
     StringBuilder sb = new StringBuilder(); 
     sb.AppendLine("*** V E G I T E M S ***"); 
     foreach(var item in VegeratianMenu) 
     { 
      sb.AppendLine("************************"); 
      sb.AppendLine(item.ToString()); 
     } 
     return sb.ToString(); 
    } 
    public void Print() 
    { 
     Console.WriteLine(ToString()); 
    } 
    public void PrintVegenerian() 
    { 
     Console.WriteLine(ToVegetarianString()); 
    } 
} 
関連する問題