2009-07-24 9 views
5

je une méthode qui accepte un paramètre obj de type System.ObjectLa meilleure façon de tester si un type est une collection

Maintenant, je veux vérifier si le type réel de obj est:

  • Type de collection (IEnumerable).
  • Autre chose.

La première façon dont je pensais est:

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

Mais System.String implémente IEnumerable et Je ne veux pas traiter la chaîne comme une collection.

La deuxième façon que je pensais est de tester ICollection au lieu de IEnumerable, car IEnumerable est plus d'une collection potentielle que réelle. Cela exclurait la chaîne, mais aussi ICollection-Of-T parce qu'elle n'hérite pas de ICollection (IEnumerable-Of-T est la seule abstraction de collection générique qui soit rétrocompatible - elle hérite de IEnumerable).

donc je suppose que la meilleure façon est:

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

Y at-il une meilleure façon?

+0

Je considère les énumératifs comme des SEQUENCES, pas comme des COLLECTIONS. Il y a peut-être une subtile différence de sens là-bas; puisque je ne connais pas votre demande, je ne sais pas si c'est relavent. Nous avons rencontré ce problème lors de la conception des initialiseurs de collection. Il y a beaucoup de "collections" qui n'implémentent pas ICollection, et il y a beaucoup d'objets qui implémentent des Add qui ne sont pas des collections. (Objets mathématiques, typiquement.) Nous avons décidé d'utiliser une heuristique. Si un type implémente IEnumerable et possède une méthode Add publique, il s'agit probablement d'une collection. C'est un peu loufoque, mais en pratique cela fonctionne. –

+0

Ceci est une bonne ressource relative aux abstractions de collection: http://blogs.msdn.com/brada/archive/2005/01/18/355755.aspx –

Répondre

6

Je pense que vous compliquez un peu ce problème. Si vous voulez vraiment utiliser IEnumerable mais exclure System.String, pourquoi ne pas le faire directement dans le code?

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

Cela semble être la seule façon de le faire. Je pense que lorsque les gars de BCL ont conçu le type String, ils ne se sont pas rendu compte à quel point IEnumerable deviendrait le seul moyen de se référer à n'importe quelle collection. –

5

Si vous avez vraiment voulez tester: (pourquoi, par la voie)

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

Mais franchement, si vous voulez vraiment que pour cas particulier string, puis juste le faire. Si vous testez pour ICollection<>, vous traiterez le résultat d'une requête LINQ comme "non-collection", par exemple, sans raison valable.

+0

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

Questions connexes