Domanda

A questa domanda ha già una risposta qui:

Stavo attraversando Asp.Net MVC lezione e ho imparato che, per un metodo per qualificarsi come azione per un controller,

  • Non deve avere un "aprire generico tipo"

Capisco un po ' generici e li usa in una certa misura, ma:

  • Che cosa è un tipo generico aperto in .Net.
  • C'è una tale cosa come un chiuso di tipo generico?
  • Tipo generico aperto è un termine che non viene utilizzato molto spesso.Che cosa è utilizzato / confuso con esso ?
È stato utile?

Soluzione

Il linguaggio C # definisce un tipo aperto per essere un tipo che è sia un argomento di tipo o di un tipo generico definito con argomenti di tipo sconosciuto:

  

Tutti i tipi possono essere classificate come tipi aperti o chiusi i tipi. Un tipo aperto è un tipo che coinvolge parametri di tipo. Più in particolare:

     
      
  • parametro Un tipo definisce un tipo aperto.
  •   
  • Un tipo di matrice è del tipo aperto se e solo se il suo tipo di elemento è del tipo aperto.
  •   
  • A tipo costruito è del tipo aperto se e solo se uno o più dei suoi argomenti di tipo è un tipo aperto . A tipo annidato costruito è un tipo aperto se e solo se uno o più dei suoi argomenti o di tipo argomenti di questo tipo contenenti (s) è del tipo aperto.
  •   
     

tipo chiuso è un tipo che non è del tipo aperto.

Pertanto T, List<T> e Dictionary<string,T> e Dictionary<T,U> sono tutti i tipi aperti (T e U sono argomenti di tipo) mentre List<int> e Dictionary<string,int> sono tipi chiusi.

C'è un concetto relativo: un non legato tipo generico è un tipo generico con argomenti di tipo non specificato. Un tipo non legato non può essere utilizzato nelle espressioni diverse typeof() e non è possibile creare un'istanza o chiamare i suoi metodi. Per esempio, List<> e Dictionary<,> sono tipi non legati.

Per chiarire la sottile distinzione tra un tipo aperto e di tipo non legato:

class Program {
   static void Main() { Test<int>(); }
   static void Test<T>() {
      Console.WriteLine(typeof(List<T>)); // Print out the type name
   }
}

Se si esegue questo frammento di codice, sarà stampare

System.Collections.Generic.List`1[System.Int32]

che è il nome CLR per List<int>. E 'chiaro in fase di esecuzione che l'argomento tipo è System.Int32. Questo rende List<T> un legato tipo aperto.

In fase di runtime, è possibile utilizzare la reflection per argomenti di tipo si legano ai parametri di tipo non specificato di tipi generici non legati con il metodo Type.MakeGenericType :

Type unboundGenericList = typeof(List<>);
Type listOfInt = unboundGenericList.MakeGenericType(typeof(int));
if (listOfInt == typeof(List<int>))
     Console.WriteLine("Constructed a List<int> type.");

È possibile controllare se un tipo è un tipo generico non legato ( definizione di tipo generico ) da cui è possibile costruire tipi rilegati con la Type.IsGenericTypeDefinition proprietà :

Console.WriteLine(typeof(Dictionary<,>).IsGenericTypeDefinition); // True
Console.WriteLine(typeof(Dictionary<int,int>).IsGenericTypeDefinition); // False

Per ottenere il tipo non legato da un tipo costruito in fase di esecuzione, è possibile utilizzare il Type.GetGenericTypeDefinition metodo .

Type listOfInt = typeof(List<int>);
Type list = listOfInt.GetGenericTypeDefinition(); // == typeof(List<>)

Si noti che per un tipo generico, è possibile avere una definizione di tipo completamente non legato, o una definizione completamente vincolata. Si può non vincola alcuni parametri di tipo e altri lasciano non legato. Per esempio, non si può avere Dictionary<int,> o Dictionary<,string>.

Altri suggerimenti

Giusto per aggiungere:

Dictionary<string, T> (o più precisamente Dictionary<string,>) è ancora un tipo aperto.

Esempio:

void Foo<T>(Dictionary<string,T> dic) { ... }

Un "aperto tipo generico" è solo un tipo generico che non c'è ancora il tipo specificato (ad esempio, CargoCrate<T>). Si diventa "chiuso" una volta un tipo concreto è stato assegnato (ad esempio CargoCrate<Widget>).

Per esempio, supponiamo di avere qualcosa di simile:

public class Basket<T> {
  T[] basketItems;
}

public class PicnicBlanket<T> {
  Basket<T> picnicBasket;   // Open type here. We don't know what T is.
}

                                 // Closed type here: T is Food.
public class ParkPicnicBlanket : PicnicBlanket<Food> {
}

Qui, il tipo di picnicBasket è aperto: nulla è stato ancora assegnato a T. Quando si effettua una PicnicBlanket cemento con un tipo specifico - ad esempio, scrivendo PicnicBlanket<Food> p = new PicnicBlanket<Food>() - noi ora chiamiamo chiuso

.

Ci sono tre tipi di tipi generici.Per farla breve, in questo (semplificato) dichiarazione:

public class Dictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
  • Dictionary<TKey, TValue> è un sovrabbondanza di tipo generico.

  • KeyValuePair<TKey, TValue> è, in questo caso, un costruito aperto di tipo generico.Ha alcuni parametri di tipo, ma sono già definiti altrove (in Dizionario, in questo caso).

  • Dictionary<string, int> sarebbe un costruito chiuso di tipo generico.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top