2015-09-23 15 views
7

Ho una classe generica con una sottoclasse che fornisce tipi specifici.Puoi creare una sottoclasse di una classe generica con una classe tipizzata specifica?

public abstract class GenericBase<T> 
    where T:Interface1 
{ 
} 

ho sottoclasse i farmaci generici con le implementazioni specifiche:

public class Customer: 
    GenericBase<Type1> 

(Type1 attrezzi Interface1).

Ho un'altra classe di base astratta che ha un riferimento alla presente:

protected GenericBase<Interface1> genericInstance; 

Infine, quando si tenta di assegnare il genericInstance a un'istanza della classe base, mi dà un errore del compilatore, dicendo che "Impossibile convertire implicitamente il cliente in GenericBase <Interface1>".

base.genericInstance = new Customer(); //Compiler error 

non capisco perché dovrei ottenere questo errore se Customer è un sottotipo di GenericBase<Type1>, e Type1 implementa Interface1. Customer è effettivamente un tipo di GenericBase<Interface1>, se è una sottoclasse di GenericBase<Type1>?

Presumo che io stia fraintendendo qualcosa sui generici qui; c'è un modo per consentire questo comportamento?

+0

Non sono sicuro in C#, ma questo sicuramente non funziona in Java. In Java, 'genericInstance' dovrebbe essere dichiarato come' GenericBase protetto genericInstance' (nota: non l'ho provato per vedere se effettivamente funziona). – Powerlord

+1

[Covarianza e contro-varianza] (https://msdn.microsoft.com/en-us/library/ee207183) –

+0

La regola generale è che i generici non sono covarianti perché non si può sapere cosa si farà con esso. Non posso assegnare un 'Elenco ' a un 'Elenco ' perché altrimenti, sarei in grado di aggiungere un 'Cane' alla' Lista 'nonostante sia davvero un' Elenco ' – Powerlord

risposta

9

In C#, la covarianza (assegnando un tipo derivato a un tipo di base) non può essere applicata alle classi generiche. Di conseguenza, è necessario applicare un'interfaccia specificatamente contrassegnata come covariante, utilizzando out parameter modifier su una nuova interfaccia IGenericBase.

protected IGenericBase<Interface1> genericInstance = new Customer(); 

public interface IGenericBase<out T> {} 

public abstract class GenericBase<T> : IGenericBase<T> 
    where T:Interface1 {} 

public interface Interface1 {} 

public class Type1 : Interface1 {} 

public class Customer: GenericBase<Type1> {} 
+2

Sapevo che C# aveva operatori simili alla strana '' di Java e '', non sapevo che fossero '' e ''. – Powerlord

+0

Non ero in grado di utilizzare un'interfaccia covariante perché i miei tipi venivano utilizzati sia come valori di ritorno che come parametri di input nella mia interfaccia. Ma almeno ora capisco un po 'di covarianza; qualcosa che non avevo affrontato prima. – GendoIkari

4

C# non ha covarianza di classi generiche, il che significa che non è possibile assegnare un valore con un argomento di tipo derivato più a una variabile con un argomento di tipo derivato meno.

Ciò funzionerebbe con le interfacce, tuttavia, a condizione che alcune condizioni siano soddisfatte, vale a dire, se il tipo di parametro viene utilizzato solo in posizioni covarianti, cioè come un tipo di ritorno di metodi e proprietà.

Vedere this e altri bit di documentazione per ulteriori informazioni.

Problemi correlati