2009-06-17 29 views
9

Spesso mi trovo in una situazione in cui creo un'interfaccia o una classe generica e quindi desidero utilizzare versioni diverse di questa classe o interfaccia in un modo non generico. Per esempio io possa avere un'interfaccia come questa:Versioni non generiche di classi e interfacce generiche

interface ICanCreate<T> 
{ 
    T NewObject(); 
} 

che consente una classe di essere una fabbrica per quel tipo. Allora voglio registrare questi con una classe generale fabbrica quindi provo a scrivere qualcosa del genere:

public class Factory 
{ 
    private Dictionary<Type, ICanCreate> mappings; // what do I put here???? 

    public void RegisterCreator<T>(ICanCreate<T> creator) 
    {    
    } 

    public T Create<T>() 
    {    
    } 
} 

Nel dizionario, che tipo devo utilizzare per il mio valore? Non so se mi manca una sorta di principio di progettazione e sono consapevole che questo ha molto a che fare con la varianza co (ntra?). Qualsiasi aiuto o idea sarebbe molto apprezzato.

risposta

11

O si hanno di utilizzare solo object nella dichiarazione dizionario (è tutto privato e si possibile verificare che non avrai mai messo il tipo sbagliato di cosa in là) o dichiarare un'interfaccia non generica ICanCreate che ICanCreate<T> si estende.

Fondamentalmente si desidera una relazione di tipo che non può essere espressa in C# - e ogni volta che accade, si finisce con una soluzione leggermente sgradevole, ma sembra che si possa isolare la bruttezza qui (cioè tenerlo all'interno del singolo classe).

+0

Cosa diresti è il più preferito uno dei due? Vado sempre per la soluzione numero due se sono in questa situazione, credendo che sia una soluzione più elegante. È, o non importa? – Razzie

+2

Ci sono membri che potresti inserire sensibilmente nell'interfaccia non generica? Se l'interfaccia è * solo * il metodo Create, allora rimango con l'oggetto: l'interfaccia non generica non ti darebbe alcunché. In altri casi, si può essere in grado di farla franca solo facendo riferimento all'interfaccia non generica in cui non si conosce l'argomento del tipo giusto, nel qual caso ciò fornisce un vantaggio evidente. –

+0

Cancella, grazie per il commento! – Razzie

3

interessante notare che questo è un problema che si risolve in C# 4.0:

public interface ICanCreate<out T> // covariant 
{ 
    T NewObject(); 
} 

public class Factory 
{ 
    private Dictionary<Type, ICanCreate<object>> mappings = new Dictionary<Type, ICanCreate<object>>(); 

    public void RegisterCreator<T>(ICanCreate<T> creator) where T:class 
    {    
     mappings[typeof(T)] = creator; 
    } 

    public T Create<T>() 
    {    
     ICanCreate<object> creator = mappings[typeof(T)]; 
     return (T) creator.NewObject(); // I do not think you can get rid of this cast 
    } 
} 
+0

Cosa significa 'out T'? – Svish

+0

@Svish: contrassegna T come covariante. –

+0

Hm .. cosa significa? Hai un link con maggiori informazioni su questo o qualcosa del genere? – Svish

Problemi correlati