Pregunta

    

Esta pregunta ya tiene una respuesta aquí:

    
            
  •              Generics -Abrir y tipos construidos cerradas                                      3 respuestas                          
  •     
    

Yo estaba pasando por Asp.Net MVC lección y aprendido que, para un método para calificar como una acción de un controlador,

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

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

  • ¿Qué es un tipo genérico abierto en .Net.
  • ¿Hay una cosa tal como un tipo genérico cerrado ?
  • tipo genérico Abrir es un término no se usa muy a menudo. Lo que se usa / confundirse con ella?
¿Fue útil?

Solución

El lenguaje C # define un tipo abierto para ser un tipo que de ya sea un argumento 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 involucra a los parámetros de tipo. Más específicamente:

     
      
  • parámetro A tipo define un tipo abierto.
  •   
  • un tipo de matriz es un tipo abierto si y sólo si su tipo de elemento es un tipo abierto.
  •   
  • A tipo construido es un tipo abierto si y sólo si una o más de sus argumentos de tipo es un tipo abierto . A tipo anidado construido es un tipo abierto si y sólo si una o más de sus argumentos de tipo o de los argumentos de tipo de su tipo que contienen (s) es un tipo abierto.
  •   
     

tipo cerrado es un tipo que no es un 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 List<int> y Dictionary<string,int> son tipos cerrados.

No es un concepto relacionado: Un tipo genérico no unido es un tipo genérico con argumentos de tipo no especificado. Un tipo no unida no puede usarse 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 unidos.

Para aclarar la 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

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

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

En tiempo de ejecución, se puede utilizar la reflexión a argumentos de tipo se unen a los parámetros de tipo no especificado de tipos genéricos no unidas 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.");

Se puede comprobar si un tipo es un tipo genérico no unida ( tipo genérico definición ) desde el que se puede construir tipos ligados a la Type.IsGenericTypeDefinition propiedad :

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, se puede utilizar el Type.GetGenericTypeDefinition método .

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

Tenga en cuenta que para un tipo genérico, que o bien puede tener una definición de tipo completamente sin consolidar o una definición completamente atado. Puede no se unen algunos parámetros de tipo y dejar que otros no unido. Por ejemplo, no se puede tener Dictionary<int,> o Dictionary<,string>.

Otros consejos

Sólo para añadir:

Dictionary<string, T> (o más precisamente Dictionary<string,>) es todavía un tipo abierto.

Ejemplo:

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

Un "tipo genérico abierto" es sólo un tipo genérico que no tienen todavía su tipo especificado (por ejemplo, CargoCrate<T>). Se convierte en "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> {
}

A continuación, el tipo de picnicBasket está abierto: nada todavía ha sido asignado a T. Cuando haces una PicnicBlanket hormigón con un tipo específico - por ejemplo, escribiendo PicnicBlanket<Food> p = new PicnicBlanket<Food>() - ahora lo llamamos cerrado

.

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 tipo genérico sin límites .

  • KeyValuePair<TKey, TValue> es, en este caso, un abierto construido tipo genérico . Tiene algunos parámetros de tipo, pero que ya se definen en otra parte (en el diccionario, en este caso).

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top