Generici: tipi aperti e chiusi

Recentemente ho notato che i tipi generici costruiti possono essere aperti e chiusi. Ma non capisco cosa intendano in realtà. Puoi fare un semplice esempio?

In pratica, la terminologia non ha molta importanza – non riesco a ricordare l’ultima volta che ho dovuto preoccuparmene tranne quando ho provato a scriverne.

  • Un tipo non associato non ha argomenti tipo specificati
  • Un tipo costruito ha almeno un argomento di tipo specificato
  • Un parametro di tipo è un tipo aperto
  • Un tipo di matrice in cui è aperto il tipo di elemento è un tipo aperto
  • Un tipo aperto costruito ha almeno un argomento di tipo che è un tipo aperto
  • Un tipo chiuso è qualsiasi tipo che non è aperto

(Esistono ulteriori regole per i tipi annidati. Consulta la sezione 4.4 delle specifiche C # 3.0 per i dettagli di carattere cruento.)

Come esempio di un tipo aperto aperto, considera:

public class NameDictionary : Dictionary 

La class base di typeof(NameDictionary<>) è:

  • Costruito perché specifica argomenti di tipo
  • Apri perché il secondo argomento di tipo ( T ) è un tipo aperto

I documenti MSDN per Type.IsGenericType hanno una tabella molto utile.

Solo per ribadire, questo è quasi del tutto irrilevante nell’uso quotidiano.

Generalmente sono favorevole alla conoscenza della terminologia corretta, in particolare per cose come “passaggio per riferimento” ecc., Ma in questo caso, in realtà, non si presenta molto spesso. Mi piacerebbe scoraggiarti triggersmente dal preoccuparti di questo 🙂

Da MSDN :

Un tipo o un metodo generico viene chiuso se i tipi di elementi istantanei sono stati sostituiti per tutti i parametri del tipo, inclusi tutti i parametri di tipo di tutti i tipi di allegato. È ansible creare un’istanza di un tipo generico solo se è chiusa.

Quindi funziona come List è chiuso :

 var list = Activator.CreateInstance(typeof(List)); 

Ma ciò genera un’eccezione in fase di esecuzione perché è aperto List<> :

 var list = Activator.CreateInstance(typeof(List<>)); ↑ 

Ho usato principalmente generici aperti (fondamentalmente generici non motivati) nelle mappature delle dipendenze. Ad esempio, qualcosa di simile

 Bind>() .To>() 

Quindi, quando il mio costruttore di oggetti contiene:

 public SomethingController(IRepository) { ... } 

Il mio meccanismo di iniezione di dipendenza istanzia un object di base automagicamente. (Funziona con Ninject e StructureMap e probabilmente con la libreria Castle Windsor, non sono sicuro di altri framework).