2010-01-31 6 views
100

yo estaba pasando por Asp.Net MVC lesson y aprendido que, para un método para calificar como una acción de un controlador,¿Qué es exactamente un "tipo genérico abierto" en .NET?

  • No debe tener un "abierto tipo genérico"

entiendo genéricos un poco y utilizarlos en cierta medida, pero:

  • ¿Qué es un abierta tipo genérico en .Net.
  • ¿Existe un tipo genérico cerrado ?
  • Tipo genérico abierto es un término que no se usa con mucha frecuencia. ¿Qué se usa/confunde con eso?

Respuesta

168

El lenguaje C# define un tipo abierto a ser un tipo que es bien un argumento de tipo o un tipo genérico definido con argumentos de tipo desconocido:

Todos los tipos se pueden clasificar como cualquiera de los tipos abiertos o tipos cerrados . Un tipo abierto es un tipo que implica parámetros de tipo. Más específicamente:

  • Un tipo de parámetro define un tipo abierto.
  • Un tipo de matriz es un tipo abierto si y solo si su tipo de elemento es de tipo abierto.
  • A tipo construido es un tipo abierto si y solo si uno o más de sus argumentos de tipo es tipo abierto. Un tipo anidado construido es un tipo abierto si y solo si uno o más de sus argumentos de tipo o los argumentos de tipo de su tipo (s) contiene un tipo abierto.

A tipo cerrado es un tipo que no es de tipo abierto.

Por lo tanto T, List<T> y Dictionary<string,T> y Dictionary<T,U> son todos los tipos abiertos (T y U son argumentos de tipo) mientras que los tipos List<int> y Dictionary<string,int> están cerrados.

Existe un concepto relacionado: Un tipo genérico no vinculado es un tipo genérico con argumentos de tipo no especificado. Un tipo no vinculado no se puede usar en expresiones que no sean typeof() y no se puede crear una instancia o llamar a sus métodos. Por ejemplo, List<> y Dictionary<,> son tipos no vinculados.

Para aclarar el sutil distinción entre un tipo abierto y un tipo sin unir:

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

Si ejecuta este fragmento, que va a imprimir las

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

que es el nombre de CLR para List<int> . Está claro en el tiempo de ejecución que el argumento tipo es System.Int32. Esto hace List<T> un obligado tipo abierto.

En tiempo de ejecución, se puede utilizar la reflexión para unir argumentos de tipo a los parámetros de tipo no especificado de tipos genéricos no unidas con el Type.MakeGenericType method:

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

Puede comprobar si un tipo es un tipo genérico no unida (definición de tipo genérico) desde donde se puede construir tipos ligados a la Type.IsGenericTypeDefinition property:

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

para obtener el tipo no unido de un tipo construido en tiempo de ejecución, puede utilizar el Type.GetGenericTypeDefinition method.

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

Tenga en cuenta que para un tipo genérico, puede tener una definición de tipo completamente independiente, o una definición completamente enlazada. No puede enlazar algunos parámetros de tipo y dejar otros sin unir. Por ejemplo, no puede tener Dictionary<int,> o Dictionary<,string>.

+8

+1 buena información - Aprendí algo nuevo hoy. Sabía que List <> era un tipo genérico, pero ahora sé el término técnico correcto. – IAbstract

+2

Usted * puede * cerrar parcialmente un tipo genérico al proporcionar un argumento de tipo que en sí mismo es un tipo genérico abierto. Sin embargo, este es un callejón sin salida. El marco no reconoce oficialmente este estado parcial, tratándolo como cerrado o abierto, por lo que no le permite hacer nada útil con él. –

+1

gran explicación en cuanto a la diferencia entre el tipo abierto y el tipo sin encuadernar, ¡no sabía antes! – nawfal

5

Un "tipo genérico abierto" es simplemente un tipo genérico que aún no tiene su tipo especificado (por ejemplo, CargoCrate<T>). Se vuelve "cerrado" una vez que se ha asignado un tipo concreto (por ejemplo, CargoCrate<Widget>).

Por ejemplo, supongamos que tiene algo como esto:

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> { 
} 

Aquí, el tipo picnicBasket 's está abierto: nada todavía ha sido asignado a T. Cuando crea un PicnicBlanket concreto con un tipo específico, por ejemplo, escribiendo PicnicBlanket<Food> p = new PicnicBlanket<Food>(), ahora lo llamamos cerrado.

8

sólo para añadir:

Dictionary<string, T> (o más precisamente Dictionary<string,>) sigue siendo un tipo abierto.

Ejemplo:

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

@Mehrdad Afshari: Lo siento, pero igual puede obtener lo que llama tipos semicerrados ... – leppie

+0

Además, no tengo idea de cómo construir eso (o representar el tipo), podría ser una pregunta que valga la pena. – leppie

+0

@Mehrdad Afshari: parece bastante abierto para mí, pero también estoy abierto a sugerencias. :) – leppie

4

Hay tres clases de tipos genéricos. Para ser breves, en esta declaración (simplificado):

public class Dictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>> 
  • Dictionary<TKey, TValue> es un ilimitada tipo genérico.

  • KeyValuePair<TKey, TValue> es, en este caso, tipo genérico abierto.Tiene algunos parámetros de tipo, pero ya están definidos en otra parte (en Diccionario, en este caso).

  • Dictionary<string, int> sería cerrado construido tipo genérico.

Cuestiones relacionadas