variable type new generic c# .net generics open-generics

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í:

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 .