Quindi sto usando un framework C # che ha un ottimo esempio di dove i generici sarebbero utili, tranne che non erano usati. Per ragioni di semplicità, diremo che si trattava di una lista (so che C # ha una sua lista), ma invece di essere Elenco in cui posso specificare il T, lo hanno reso List, risultando in un tipo di controllo da incubo per tutto il codice.
Voglio correggerlo, ma non posso modificare il framework.
Quindi vedo tre modi per risolvere questo problema.
Estendi, a capo o entrambi.
Quindi la domanda di base è, qual è il modo migliore per aggiungere i generici?
Esiste un modello di design particolarmente adatto a questo?
Ora, mentre non sono sicuro che il wrapping o l'estensione siano migliori, se questo fosse un caso semplice, sarei andato con uno di loro e non avrei nemmeno considerato di farlo entrambi.
Ma il CustomList
è usato ovunque, e voglio solo sostituirlo a poco a poco.
L'estensione mi consente di usare TypedCustomList come CustomList, in modo che se cambio dove CustomList viene creato da TypedCustomList, in seguito nell'esecuzione del codice il codice può ancora trattarlo come una CustomList.
Tuttavia, non posso trattare un oggetto CustomList come TypedCustomList (anche se assicuro che il tipo generico sia corretto per quella CustomList fornita). (O mi manca come farlo, quale risolverebbe il problema?)
Se lo si avvolge, ora posso lavorare con le CustomList esistenti, ma devo esporre l'oggetto CustomList interno per passarlo ad altro codice (ad esempio, se chiamo un metodo che si aspetta CustomList, devo fare instanceOfTypedCustomList. _customList, non posso passare instanceOfTypedCustomList).
Se lo avvolgo e lo estendo, prendo una CustomList esistente e la trattiamo come una TypedCustomList pur conservando la mia TypedCustomList come lista personalizzata. Ma, come puoi vedere qui sotto, l'opzione "Entrambi" sembra la peggiore.
L'estensione
public class TypedCustomList<T> : CustomList
{
public TypedCustomList()
:base()
{
}
public T getElementAt(int i)
{
return (T) base.getElementAt(i);
}
public void addElement(T element)
{
base.addElement(element);
}
...ect.
}
Confezione:
public class TypedCustomList<T>
{
CustomList _customList { get; private set;}
public TypedCustomList(CustomList cl)
{
_customList = cl;
}
public T getElementAt(int i)
{
return (T) _customList.getElementAt(i);
}
public void addElement(T element)
{
_customList.addElement(element);
}
...ect.
}
Entrambi:
public class TypedCustomList<T> : CustomList
{
private CustomList _customList;
public TypedCustomList()
:base()
{
_customList = null;
}
public TypedCustomList(CustomList cl)
{
_customList = cl;
}
public T getElementAt(int i)
{
if(_customList == null)
{
return (T) base.getElementAt(i);
}
else
{
return (T) _customList.getElementAt(i);
}
}
public void addElement(T element)
{
if(_customList == null)
{
base.addElement(element);
}
else
{
_customList.addElement(element);
}
}
...ect.
}
P.S.
Più sfondo che potrebbe essere rilevante per il problema.
Esiste una classe che ha una CustomList che viene utilizzata in tutta l'applicazione, con diverse parti dell'applicazione con ogni istanza con tipi di oggetto diversi (oltre una dozzina in totale). Voglio che questa classe abbia una sola TypedCustomList per ogni utilizzo. Ma fino a quando non posso essere sicuro che tutti i riferimenti alla sua CustomList sono spariti, volevo aggiungere qualche gestione degli errori. Quindi stavo aggiungendo qualcosa di simile al seguente:
public ClassThatUsesCustomList
{
...
private CusotmList _list;
private TypedCustomList<SomeObject> _SomeObjectCustomList;
public CustomList list
{
get
{
//Already existing code
if(_list == null)
{
_list = new CustomList();
}
//My code
catchMissedGetSet(_list);
return _list;
}
set
{
catchMissedGetSet(value);
_list = value;
}
}
public SomeObjectCustomList
{
get
{
if(_SomeObjectCustomList == null)
{
_SomeObjectCustomList = new TypedCustomList<SomeObject>();
}
return _SomeObjectCustomList;
}
set
{
_SomeObjectCustomList = value;
}
}
private void catchMissedGetSet(CustomList cl)
{
bool findMissedSpots = true;
if(cl == null || cl.Count == 0 || cl[0] is SomeObject)
{
SomeObjectCustomList = new SomeObjectCustomList(cl); //Using wrapping.
if(findMissedSpots && System.Diagnostics.Debugger.IsAttached)
{
System.Diagnostics.Debugger.Break();
//Hey, you missed a place. Use step out to find it.
}
}
}
...
}
L'ho fatto per catturare tutti i punti che mi mancavano e per evitare eventuali bug. Mi richiede di avvolgerlo (per quanto posso dire).