2009-07-24 21 views
5

tengo un método que acepta un parámetro obj de tipo System.Objectmejor manera de probar si un tipo es una colección

Ahora quiero comprobar si el tipo real de obj es:

  • Un tipo de colección (IEnumerable).
  • Cualquier otra cosa.

La primera manera pensé es:

if (obj is IEnumerable) 
    // obj is a collection 

Pero System.String implementa IEnumerable, y no quiero para tratar la cadena como una colección.

La segunda forma que pensé es probar para ICollection en lugar de IEnumerable, ya que IEnumerable es más una colección potencial que una real. Esto dejaría de cadena, pero también ICollection-Of-T porque no hereda ICollection (IEnumerable-Of-T es la única abstracción de colección genérica que es compatible con versiones anteriores; hereda IEnumerable).

así que supongo que la mejor manera es:

if (obj is string) 
    // not a collection 
else if (obj is IEnumerable) 
    // collection 
else 
    // not a collection 

¿Hay una mejor manera?

+0

Veo enumerables como SECUENCIAS, no como COLECCIONES. Posiblemente hay una diferencia sutil en el significado allí; dado que no conozco su solicitud, no sé si eso es algo relativo. Nos enfrentamos a este problema al diseñar inicializadores de colecciones. Hay muchas "colecciones" que no implementan ICollection, y hay muchos objetos que implementan Add que no son colecciones. (Objetos matemáticos, por lo general). Decidimos usar una heurística. Si un tipo implementa IEnumerable y tiene un método Add público, probablemente sea una colección. Esto es un poco tonto, pero en la práctica funciona. –

+0

Este es un buen recurso relacionado sobre abstracciones de colecciones: http://blogs.msdn.com/brada/archive/2005/01/18/355755.aspx –

Respuesta

6

Creo que estás complicando un poco esto un poco. Si realmente quieres usar IEnumerable pero excluir System.String, ¿por qué no hacerlo directamente en el código?

public static bool IsCollection(object obj) { 
    return obj is IEnumerable && !(obj is String); 
} 
+0

Esta parece ser la única forma de hacerlo. Creo que cuando los chicos de BCL diseñaron el tipo String no se dieron cuenta de lo importante que se convertiría IEnumerable como la única forma de referirse a cualquier colección. –

5

Si realmente sólo desea la prueba: (¿por qué, por cierto)

bool isCollection = obj.GetType().GetInterfaces() 
    .Any(iface => iface.GetGenericTypeDefinition() == typeof(ICollection<>)) 

Pero, francamente, si realmente sólo desea especial de los casos string, a continuación, sólo hacerlo. Si prueba para ICollection<>, tratará el resultado de una consulta LINQ como "no recogida", por ejemplo, sin una buena razón.

+0

O 'obj.GetType(). GetInterface (" System.Collections .IEnumerable ")! = Null' – xr280xr

Cuestiones relacionadas