Come ti sommo le pere con le mele #2

Ricordate l'idiomatica soluzione per sommare Pere e Mele descritta in "Come ti sommo le pere con le mele"? Soluzione interessante anche se mi era poco soddisfacente perchè poco pulita ( e poco OOP) e troppo legata a potenzialità del linguaggio.

La problematica di trovate qualcosa di soddisfacente era sopratutto legata/limitata ai "limiti dei Generics di C# 2.0": "Nel C#2.0 non è possibile definire conversioni o relazioni di ereditarietà tra tipi ottenuti istanziando tipi generici anche se a partire da tipi tra loro in relazione di ereditarietà." (UGIdotNETWiki). La nuova soluzione è frutto di una più attenta analisi dei requisiti del caso d'uso/funzionalità. Nella prima soluzione volevo sommare esplicitamente due collezioni di frutta "public static Fruits operator +(Fruits a, Fruits b)" ma a pensarci bene NON è necessario avere esattamente una collection come secondo operatore (b) e la vera necessità è che l'oggetto da sommare possa semplicemente enumerare frutti.

  interface IFruitEnumerable : IEnumerable<Fruit> { }

Ecco quindi come si potrebbe ri-definire la collezione generica di frutti e in particolare l'overload dell'operatore "+".

  class Fruits : Collection<Fruit> 
  {
    public Fruits() { }
  
    private Fruits(IList<Fruit> list) : base(list) { }
  
    public static Fruits operator +(Fruits a, IFruitEnumerable b)
    {
      List<Fruit> list = new List<Fruit>();
      list.AddRange(a);
      list.AddRange(b);
      return new Fruits(list);
    }
  
  }

Prima di proseguire rimando al post "Generics e i ... presunti paradossi" di cui useremo la classe Enumerator<T, K> ivi definita. Poi ri-definirò le collezioni "Apples" e "Pears" eliminando l'implementazione dell'overload del casting implicito e facendo implementare loro l'interfaccia IFruitEnuemarable. Nell'implementazione delle due collection ho usanto due diverse "strategie"/soluzioni equivalenti come descritto dal diagramma di classi qui sotto riportato.

Riporto ora il codice. È omessa la definizione di "Fruit", "Apple" e "Pear" per le quali rimando alla definizione riportata nel post iniziale ("Come ti sommo le pere con le mele"?).

  class Apples : Collection<Apple>, IFruitEnumerable
  {
  
    #region IEnumerable<Fruit> Members
  
    IEnumerator<Fruit> IEnumerable<Fruit>.GetEnumerator()
    {
      return new Enumerator<Fruit, Apple>(this);
    }
  
    #endregion
  
  }
  
  abstract class BaseFruitCollection<T> : Collection<T>, IFruitEnumerable where T : Fruit
  {
    #region IEnumerable<Fruit> Members
  
    IEnumerator<Fruit> IEnumerable<Fruit>.GetEnumerator()
    {
      return new Enumerator<Fruit, T>(this);
    }
  
    #endregion
  }
  
  class Pears : BaseFruitCollection<Pear> 
  {
  
  }

Infine ecco il codice di test; lo stesso codice del post originale poichè infatti il comportamento (e quindi l'utilizzo) delle collection è rimasto invariato.

  class Program
  {
    static void Main(string[] args)
    {
      Apples apples = new Apples();
      apples.Add(new Apple());
      apples.Add(new Apple());
      apples.Add(new Apple());
  
      Pears pears = new Pears();
      pears.Add(new Pear());
      pears.Add(new Pear());
  
      Fruits fruits = new Fruits();
      fruits += apples;
      fruits += pears;
  
      Console.WriteLine(fruits.Count);
      Console.ReadLine();
    }
   }

posted @ giovedì 25 maggio 2006 11:35

Print
Comments have been closed on this topic.
«aprile»
domlunmarmergiovensab
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011