我有一个采用通用参数T的方法。在内部,要确定要调用的其他方法,我需要知道(不限制它)该参数是List还是只是。
我该怎么做?
我一直在使用
var isList = typeof(T).Name.ToLower().Contains("list`1");
但这感觉就像一个肮脏的方法。什么更干净?
答案 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
}