我的通用类型是列表,还是只是一个项目?

时间:2011-08-12 20:44:11

标签: c# generics

我有一个采用通用参数T的方法。在内部,要确定要调用的其他方法,我需要知道(不限制它)该参数是List还是只是。

我该怎么做?

我一直在使用

var isList = typeof(T).Name.ToLower().Contains("list`1");

但这感觉就像一个肮脏的方法。什么更干净?

4 个答案:

答案 0 :(得分:11)

var type = typeof(T);
bool isList = type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>);

如果您不需要List的完全匹配,您也可以只检查typeof(IList).IsAssignableFrom(typeof(T))是否是许多类似列表的集合所实现的。


如果你想直接支持T等于IList<T2>(所以类型参数T是一个接口),那么你需要单独检查它(GetGenericTypeDefinition()也可以返回{{1} })。

如果您想支持从任何typeof(IList<>)继承的任何类型T,那么您必须更具创造性。您必须枚举所有接口,检查它们是否是通用的(如上所述),然后检查接口的泛型类型是否为IList<>。此外,由于对Type的GetInterfaces()调用仅返回顶级接口,因此您需要浏览每个接口实现的所有接口(递归),以检查这些接口。我知道,丑陋。

答案 1 :(得分:2)

好吧,您可以随时使用typeof(T)is关键字,但我会再看看您的设计。

您的方法确实违背了通用方法的目的。如果必须检查泛型参数的类型,那么,您的方法不是通用的。泛型非常适用于您不关心底层类型的场景。如果您在意,那么该方法不应该是通用的,它应该被重载(可能)。如何告诉我们你在这里想要实现的目标,以便我们能够提供更多有用的回复?

答案 2 :(得分:0)

检查它是否实现了IEnumerable接口。

bool isList = T is IEnumerable;

如果T是Stack,Array或其他类似的东西,这也会返回true,但我认为这对你的目的来说已足够了。

答案 3 :(得分:0)

如果您正在寻找任何内置集合,您将检查IEnumerable。这样您就不必担心类型参数了。但是这会产生问题,因为string实现了IEnumerable。因此,你需要这样的代码:

if (typeof(T) is string) {
} else if (typeof(T) is IEnumerable) {
} else { // its something else
}