2011-08-12 39 views
5

我有一个方法需要一个通用参数T.在内部,要决定调用什么其他方法,我需要知道(不限制它)如果该参数是一个List或只是一些东西。我的泛型是一个列表,还是一个项目?

我该怎么做?

我一直在使用

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

但感觉就像一个肮脏的方法。什么更清洁?

+0

你尝试比较它与另一个列表的对象类型? – krs1

+1

如果您将其传递给'NotReallyAList '实例,则会失败。 –

+0

什么*确切*你是什么意思,当你说“名单”?你的意思是确切的类型'System.Collections.Generic.List '?或者你的意思是什么0或更多的项目?或者可以读取以及更新的任何类型的集合? – stakx

回答

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

如果您不需要为列表精确匹配,也可能只是检查是否typeof(IList).IsAssignableFrom(typeof(T)),其中有许多类似列表的集合实现。


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

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

+1

+1,因为它回答了这个问题假。作为边注,如果有一些共同的功能,随后基于类型的进一步处理的反射,可能要实现一个'过程(列表项)'方法与重载每个可能性。让编译器处理未经反射的进一步处理。虽然这可能不适用于这种情况(目前还不清楚是否列表是唯一的其他可能性)。 –

+0

我喜欢你在代码片段中获得的东西 - 但每次都会变得错误。我通过IList 作为T,但仍然失败。第二种方法给了我相同的问题。 – reallyJim

+0

接受这个答案的答案,因为它完全回答我的问题,解决了我的问题 - 包括枚举接口找到的IList <>。谢谢! – reallyJim

0

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

bool isList = T is IEnumerable; 

这也将返回true,如果T是一个堆栈,数组,或其他类似的东西,但我认为它会为你的目的就足够了。

+0

这不会编译。 – Gabe

+0

这不会编译。 'T'是一个'类型参数',但像变量一样使用。 – reallyJim

+0

你需要添加'typeof(T)'就像我的例子。 – Gabe

2

那么,你总是可以使用typeof(T)is关键字,但我会再看看你的设计。

你的方法实际上是击败了通用方法的目的。如果您必须检查泛型参数的类型,那么您的方法不是通用的。泛型非常适合您不关心底层类型的场景。如果你在乎,那么该方法不应该是通用的,它应该被重载(可能)。如何告诉我们你在这里实际想要完成什么,以便我们能够给予更多有用的回应?

+0

你真的不想知道。 :)我创建一个基本查询对象通过调用NHibernate的ISqlQuery.List()或ISqlQuery.UniqueResult的方法 - 返回存储过程的结果作为动态类型。而不是采取预先“知道”,并要求调用代码调用“单”或“名单”的方法,我想通过在后端这一决定,以帮助开发者的。 – reallyJim

+1

@reallyJim:有点像[Massive](https://github.com/robconery/massive)? –

+0

@jim Schubert是的 - 没有意识到我正在接近重新发明轮子。问题的根源在于我必须处理返回需要转换为业务对象的结果的SPROC,但我不想为其创建映射。 – reallyJim

0

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

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

根据对列表的含义的理解,“IEnumerable”可能涵盖太多东西。例如,与“IList”不同,“IEnumerable”本身是只读的:我可以例如实现一个返回斐波那契数列的IEnumerable类。你会认为这个类的一个实例是一个列表吗? – stakx

+0

@stakx - 好点,我更新了我的答案。 –

相关问题