c# - type - ¿Qué es exactamente un "tipo genérico abierto" en.NET?
gettype of generic c# (4)
El lenguaje C # define un tipo abierto como un tipo que es un argumento de tipo o un tipo genérico definido con argumentos de tipo desconocido:
Todos los tipos se pueden clasificar como tipos abiertos o cerrados. Un tipo abierto es un tipo que implica parámetros de tipo. Más específicamente:
- Un parámetro de tipo define un tipo abierto.
- Un tipo de matriz es un tipo abierto si y solo si su tipo de elemento es de tipo abierto.
- Un tipo construido es un tipo abierto si y solo si uno o más de sus argumentos de tipo es un 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.
Un 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 tipos abiertos ( T
y U
son argumentos de tipo), mientras que List<int>
y Dictionary<string,int>
son tipos cerrados .
Hay un concepto relacionado: un tipo genérico no vinculado es un tipo genérico con argumentos de tipo no especificado. Un tipo no enlazado 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 independientes.
Para aclarar la distinción sutil entre un tipo abierto y uno no vinculado:
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, se imprimirá
System.Collections.Generic.List`1[System.Int32]
que es el nombre CLR para List<int>
. Está claro en el tiempo de ejecución que el argumento de tipo es System.Int32
. Esto hace que List<T>
un tipo abierto encuadernado .
En tiempo de ejecución, puede usar la reflexión para vincular los argumentos de tipo a los parámetros de tipo no especificado de los tipos genéricos no Type.MakeGenericType
con el método Type.MakeGenericType
:
Type unboundGenericList = typeof(List<>);
Type listOfInt = unboundGenericList.MakeGenericType(typeof(int));
if (listOfInt == typeof(List<int>))
Console.WriteLine("Constructed a List<int> type.");
Puede verificar si un tipo es un tipo genérico no vinculado ( definición de tipo genérico ) a partir del cual puede construir tipos vinculados con la propiedad Type.IsGenericTypeDefinition
:
Console.WriteLine(typeof(Dictionary<,>).IsGenericTypeDefinition); // True
Console.WriteLine(typeof(Dictionary<int,int>).IsGenericTypeDefinition); // False
Para obtener el tipo independiente de un tipo construido en tiempo de ejecución, puede usar el método Type.GetGenericTypeDefinition
.
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>
.
Esta pregunta ya tiene una respuesta aquí:
- Genéricos -Estructura abierta y cerrada Tipos 3 respuestas
Estaba pasando por la lección Asp.Net MVC y aprendí que, para que un método califique como una acción para un controlador,
- No debe tener un "tipo genérico abierto"
Comprendo algo de genéricos y los uso hasta cierto punto, pero:
- Qué es un tipo genérico abierto en .Net.
- ¿Hay algo así como un tipo genérico cerrado ?
- El tipo genérico abierto es un término que no se usa con mucha frecuencia. ¿Qué se usa / confunde con eso?
Hay tres tipos de tipos genéricos. Para abreviar, en esta declaración (simplificada):
public class Dictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
Dictionary<TKey, TValue>
es un tipo genérico ilimitado .KeyValuePair<TKey, TValue>
es, en este caso, un tipo genérico abierto construido . Tiene algunos parámetros de tipo, pero ya están definidos en otra parte (en Diccionario, en este caso).Dictionary<string, int>
sería un tipo genérico cerrado y construido .
Solo para agregar:
Dictionary<string, T>
(o más precisamente Dictionary<string,>
) sigue siendo un tipo abierto.
Ejemplo:
void Foo<T>(Dictionary<string,T> dic) { ... }
Un "tipo genérico abierto" es simplemente un tipo genérico que todavía 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, di que tienes 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 de picnicBasket
está abierto: aún no se ha asignado nada a T
Cuando elabora un PicnicBlanket concreto con un tipo específico, por ejemplo, al escribir PicnicBlanket<Food> p = new PicnicBlanket<Food>()
, ahora lo llamamos cerrado .