entre ejemplos diferencia and c# .net

diferencia - ienumerable c# ejemplos



RelaciĆ³n entre Lista<> e IEnumerable<> tipo abierto (2)

Aunque John Wu escribió una buena respuesta sobre las diferencias entre una definición de tipo y los tipos reales, no creo que responda por completo al problema / pregunta formulada en el OP.

¿Hay algún método para verificar la relación entre dos tipos abiertos, o la relación solo existe en tipos cerrados?

En primer lugar, la relación siempre existe; cada List<> siempre es un IEnumerable<> , como puede ver en la definición del tipo List<T> :

public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>, ...

Pero esto no responde a su segunda pregunta, si hay una manera de verificar si existe tal relación entre dos tipos. Usted pensaría que el método IsAssignableFrom se puede usar para verificar la existencia de una relación entre los tipos de tipo abierto , pero no puede. ¿Por qué? Averigüemos en la documentación de la function IsAssignableFrom :

Type.IsAssignableFrom (Type c) Devuelve true si se cumple alguna de las siguientes condiciones:

  1. c y la instancia actual representan el mismo tipo.
  2. c se deriva directa o indirectamente de la instancia actual. c se deriva directamente de la instancia actual si se hereda de la instancia actual; c se deriva indirectamente de la instancia actual si hereda de una sucesión de una o más clases que heredan de la instancia actual.

  3. La instancia actual es una interfaz que implementa c.

  4. c es un parámetro de tipo genérico, y la instancia actual representa una de las restricciones de c.

y falso si ninguna de estas condiciones es verdadera, o si c es nulo.

En su caso, ninguna de las condiciones mencionadas anteriormente resultará verdadera como: (1) no son del mismo tipo. (2) No se pueden derivar entre sí ya que son tipos abiertos: sus parámetros de tipo genérico son desconocidos ( unknown != unknown ). La List<> implementa el tipo cerrado IEnumerable<T> y no el tipo abierto IEnumerable<> (3). No son parámetros de tipo genérico (4).

Para saber si dos tipos genéricos tienen una relación, deberá inspeccionar sus type definitions (y sus interfaces / tipos base anidados) y validar que tienen una relación:

public static bool IsAssignableToOpenGenericType(Type givenType, Type genericType) { var interfaceTypes = givenType.GetInterfaces(); foreach (var it in interfaceTypes) { if (it.IsGenericType && it.GetGenericTypeDefinition() == genericType) return true; } if (givenType.IsGenericType && givenType.GetGenericTypeDefinition() == genericType) return true; Type baseType = givenType.BaseType; if (baseType == null) return false; return IsAssignableToGenericType(baseType, genericType); }

(source)

Resultará en:

var typ1 = typeof(List<>); var typ2 = typeof(IEnumerable<>); // true, List<>''s type definition contains an IEnumerable<> Console.WriteLine(IsAssignableToOpenGenericType(typ1, typ2)); // false, IEnumerable<>''s type definition does not contain List<> Console.WriteLine(IsAssignableToOpenGenericType(typ2, typ1));

¿Hay alguna relación entre los tipos abiertos List<> e IEnumerable<> ?

Ejemplo:

var type1 = typeof(List<>); var type2 = typeof(IEnumerable<>); //return false type2.IsAssignableFrom(type1);

¿Hay algún método para verificar la relación entre dos tipos abiertos, o la relación solo existe en tipos cerrados?


List<> e IEnumerable<> no son tipos; Son definiciones de tipo . Como tal, realmente no tiene sentido preguntar si uno es asignable al otro. Ninguno puede ser asignado a. No puede declarar una List<> a = null variables List<> a = null , por ejemplo: obtendrá un error de compilación "Uso inesperado de un nombre genérico no vinculado".

Una definición de tipo se convierte en un tipo genérico cuando se especifica el parámetro de tipo. En ese punto, es un tipo y se puede asignar a. Entonces, por ejemplo, la List<string> se puede asignar a IEnumerable<string> .

Si tiene en mente una definición de tipo y desea realizar una verificación de compatibilidad de tipo, simplemente use <object> (o un tipo adecuado si hay una restricción de tipo) en lugar de <> :

var type1 = typeof(List<object>); var type2 = typeof(IEnumerable<object>); //returns true type2.IsAssignableFrom(type1);