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>
.
+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
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. –
gran explicación en cuanto a la diferencia entre el tipo abierto y el tipo sin encuadernar, ¡no sabía antes! – nawfal