2009-07-24 6 views
5

Ich habe eine Methode, die einen Parameter obj vom Typ System.Objectbeste Art und Weise zu testen, ob ein Typ eine Sammlung ist

Jetzt möchte ich überprüfen, ob der tatsächliche Typ von obj akzeptiert:

  • Ein Sammlungstyp (IEnumerable).
  • Sonst noch etwas.

Der erste Weg, dachte ich an ist:

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

Aber System.String implementiert IEnumerable, und Ich will nicht Zeichenfolge als eine Sammlung behandeln.

Die zweite Möglichkeit, die ich dachte, testet für ICollection statt IEnumerable, da IEnumerable eher eine potenzielle Sammlung als eine tatsächliche ist. Dies würde String auslassen, aber auch ICollection-Of-T, weil ICollection nicht erbt (IEnumerable-Of-T ist die einzige generische Auflistungsabstraktion, die abwärtskompatibel ist - sie erbt IEnumerable).

Also ich denke, der beste Weg ist:

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

Gibt es einen besseren Weg?

+0

Ich sehe enumerables als Abfolgen, nicht als Sammlungen. Es gibt möglicherweise einen subtilen Unterschied in der Bedeutung dort; Da ich Ihre Bewerbung nicht kenne, weiß ich nicht, ob das relavent ist. Wir haben dieses Problem beim Entwerfen von Sammlungsinitialisierern angegangen. Es gibt viele "Collections", die ICollection nicht implementieren, und es gibt viele Objekte, die Add implementieren, die keine Collections sind. (Typischerweise Math-Objekte.) Wir entschieden uns für eine Heuristik. Wenn ein Typ sowohl IEnumerable als auch eine öffentliche Add-Methode implementiert, handelt es sich wahrscheinlich um eine Auflistung. Das ist ein bisschen doof, aber in der Praxis funktioniert es. –

+0

Dies ist eine gute verwandte Ressource über Sammlung Abstraktionen: http://blogs.msdn.com/brada/archive/2005/01/18/355755.aspx –

Antwort

6

Ich denke, du bist über das Komplizieren dieses ein bisschen. Wenn Sie IEnumerable wirklich verwenden, aber System.String ausschließen möchten, warum tun Sie das nicht direkt im Code?

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

Dies scheint der einzige Weg zu sein, dies zu tun. Ich denke, als die Jungs von BCL den String-Typ entwarfen, wurde ihnen nicht klar, wie wichtig IEnumerable als einziger Weg sein würde, auf irgendeine Sammlung zu verweisen. –

5

Wenn Sie wirklich nur testen wollen: (warum, übrigens)

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

Aber ehrlich gesagt, wenn Sie wirklich wollen nur auf einen speziellen Fall string, dann tun nur so. Wenn Sie für ICollection<> testen, behandeln Sie das Ergebnis einer LINQ-Abfrage beispielsweise aus keinem guten Grund als "Nicht-Sammlung".

+0

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

Verwandte Themen