2009-07-24 33 views
5

我有一個接受一個參數OBJ System.Object類型的最佳方式,如果一個類型是一家集

現在我要檢查,如果obj的實際類型的方法:

  • 集合類型(IEnumerable)。
  • 別的。

我想到的第一個辦法是:

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

但System.String實現IEnumerable,並我不想把字符串作爲一個集合

我認爲第二種方式是測試ICollection,而不是IEnumerable,因爲IEnumerable比實際的集合更具潛在收藏價值。這將省去字符串,但也ICollection-Of-T,因爲它不繼承ICollection(IEnumerable-Of-T是唯一的向後兼容的通用集合抽象 - 它繼承IEnumerable)。

所以我想最好的辦法是:

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

有沒有更好的辦法?

+0

我將枚舉視爲SEQUENCES,而不是COLLECTIONS。那裏的含義可能有微妙的差異;因爲我不知道你的申請,我不知道這是否是相關的。設計集合初始化器時,我們遇到了這個問題。有很多沒有實現ICollection的「集合」,並且有很多實現Add的對象不是集合。 (通常是數學對象)。我們決定使用啓發式。如果一個類型既實現IEnumerable並且有一個公共的Add方法,它可能是一個集合。這有點愚蠢,但在實踐中它有效。 – 2009-07-26 14:30:32

+0

這是一個關於收集抽象的好相關資源: http://blogs.msdn.com/brada/archive/2005/01/18/355755.aspx – 2009-07-30 06:34:33

回答

6

我認爲你已經完成了這一點複雜化。如果你真的想使用IEnumerable但是排除System.String,那麼爲什麼不直接在代碼中直接做呢?

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

這似乎是唯一的方法。我認爲當BCL傢伙設計了字符串類型時,他們並沒有意識到IEnumerable將成爲引用任何集合的唯一方式。 – 2009-07-25 20:50:28

5

如果你真的只是想測試:(?爲什麼,順便說一句)

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

但坦率地說,如果你真的只想特殊情況string,那麼就這樣做。如果您測試了ICollection<>,那麼您將把LINQ查詢的結果視爲「非集合」,例如,沒有很好的理由。

+0

或'obj.GetType()。GetInterface(「System.Collections .IEnumerable「)!= null' – xr280xr 2015-05-22 17:54:24