Best way to test if a Type is a collection
我有一个方法接受System.Object类型的参数obj
现在我想检查obj的实际类型是否是:
我首先想到的是:
1 2
| if (obj is IEnumerable )
// obj is a collection |
但System.String实现了IEnumerable,我不想将String视为集合。
我认为第二种方法是测试ICollection而不是IEnumerable,因为IEnumerable更像是一个潜在的集合,而不是实际的集合。这将省去字符串,但也省去了ICollection-of-T,因为它不继承ICollection(IEnumerable-of-T是唯一向后兼容的通用集合抽象,它继承了IEnumerable)。
所以我想最好的办法是:
1 2 3 4 5 6
| if (obj is string)
// not a collection
else if (obj is IEnumerable )
// collection
else
// not a collection |
有更好的方法吗?
- 我将可枚举项视为序列,而不是集合。这里的意思可能有细微的差别;因为我不知道你的应用程序,所以我不知道这是否相关。在设计集合初始值设定项时,我们遇到了这个问题。有很多不实现ICollection的"集合",还有很多实现Add的对象,这些对象不是集合。(通常是数学对象)我们决定使用启发式。如果类型同时实现IEnumerable并具有公共的Add方法,则它可能是一个集合。这有点愚蠢,但实际上是可行的。
- 这是一个关于集合抽象的很好的相关资源:blogs.msdn.com/brada/archive/2005/01/18/355755.aspx
我觉得你把这件事弄得有点复杂了。如果您真的想使用IEnumerable但不包括System.String,为什么不直接在代码中这样做呢?
1 2 3
| public static bool IsCollection (object obj ) {
return obj is IEnumerable && !(obj is String);
} |
- 这似乎是唯一的办法。我认为,当BCL设计字符串类型时,他们没有意识到IEnumerable作为引用任何集合的唯一方法有多重要。
如果您真的只想测试:
1 2
| bool isCollection = obj .GetType().GetInterfaces()
.Any(iface => iface .GetGenericTypeDefinition() == typeof(ICollection <>)) |
但坦率地说,如果你真的只想特例string(顺便问一下,为什么?),那么就这么做。如果您测试ICollection<>,您将把LINQ查询的结果视为"非集合",例如,没有好的理由。
- 或obj.GetType().GetInterface("System.Collections.IEnumerable") != null。