C# 检查传递的对象是否为IEnumerable<;T>;或单个值-包括T作为值类型
在我的C#代码的一部分中,我使用以下代码检查传入的对象是单个值还是实现了C# 检查传递的对象是否为IEnumerable<;T>;或单个值-包括T作为值类型,c#,generics,ienumerable,C#,Generics,Ienumerable,在我的C#代码的一部分中,我使用以下代码检查传入的对象是单个值还是实现了IEnumerable(T是字符串、双精度、int等,而不是复杂的对象或类): 它在所有情况下都工作得很好,直到今天,我传入了一个int[],我发现这是一个问题 那么,获取也包含值类型的IEnumerable的底层类型的最佳方法是什么 谢谢 一个IEnumerable没有底层类型,至少除了对象之外。您知道序列中的每个项都是一个对象,但您只知道这些。如果要处理所有项目都属于同一类型的项目序列(该类型不是object),则需要使
IEnumerable
(T
是字符串、双精度、int等,而不是复杂的对象或类):
它在所有情况下都工作得很好,直到今天,我传入了一个int[]
,我发现这是一个问题
那么,获取也包含值类型的IEnumerable
的底层类型的最佳方法是什么
谢谢 一个
IEnumerable
没有底层类型,至少除了对象
之外。您知道序列中的每个项都是一个对象
,但您只知道这些。如果要处理所有项目都属于同一类型的项目序列(该类型不是object
),则需要使用IEnumerable
,而不是IEnumerable
事实上,任何给定的
IEnumerable
都可能有一个字符串、一个int和一个自定义对象,它们都在同一个序列中,因此除了object
之外,没有其他通用类型,您想知道该类型以及它是否是IEnumerable
(!=string
)您需要T
?用于可以使用的阵列:
正如@Servy所说,非泛型的
IEnumerable
序列可能包含几种不同类型的元素
如果您只关心序列中的第一项,并假设所有其他项都是相同的类型,则可以尝试以下操作:
int[] paramValue = new int[] { 1, 2, 3 };
Type type = paramValue.GetType();
Type underlyingType;
if (type != typeof(string))
{
System.Collections.IEnumerable e = paramValue as System.Collections.IEnumerable;
if(e != null)
{
Type eType = e.GetType();
if(eType.IsGenericType)
{
underlyingType = eType.GetType().GetGenericArguments()[0];
}
else
{
foreach(var item in e)
{
underlyingType = item.GetType();
break;
}
}
}
}
请注意,作为一个示例,underyingtype
对于以下paramValue
将是int
:
object[] paramValue = new object[] { 1, "a", "c" };
因此,
int[]
的期望结果是int
?没错,蒂姆-我觉得我的问题措辞不正确-我现在就编辑它“,字符串…从来不是复杂的对象或类”没有意义…一些编辑会有帮助…你说的没有错,但你的评论只适用于paramValue
类型为IEnumerable
(而不是IEnumerable
)的情况。他对IEnumerable
类型的检查是a(有缺陷)检测IEnumerable
的方法,这一点可以通过他随后立即查找泛型类型T
得到隐式证明。您的答案虽然在技术上是正确的,但解决的是一个可能从未遇到过且与当前问题无关的情况。@Flater但是IEnumerable
没有泛型正如你所说,试图找到它是有缺陷的,因为它不存在。正如我在回答中所说,如果OP只想支持实现IEnumerable
的对象,而不是实现IEnumerable
的项,那么他们需要检查IEnumerable
,而不是IEnumerable
,否则他们的代码就无法工作。我觉得我只是把问题的措辞弄错了,我要传递的是一个单值或一个类型为T的IEnumerable,我需要知道T是什么…谢谢你的回答!Servy,你再次提出的问题不是问题的一部分。你所说的一切都是正确的,但与手头的问题无关。OP不是pas在字典里唱歌,他也不会通过非通用的IEnumerables。你的答案是一个有效的脚注,是重新评估方法的激励,但它不是对这里所问问题的回答。@Flater你认为OP没有通过字典的依据是什么?你认为OP没有通过i的依据是什么nIEnumerable
实例?答案是对所问问题的有效答案;它实际上回答了所问的问题,而不是你希望他们会问但没有问的问题。如果问题说他们希望得到值的元素类型,而该值只能是数组或列表,则d没有别的答案,那么当然,其他答案不会不正确,但问题不会问这个问题。如果你传入一个非泛型的IEnumerable
实例,或者一个IEnumerable
实例,其中第一个泛型参数不是序列中的项目类型,比如说,对于字典,@JohnBustos仅仅因为该方法一个或两个测试用例的rks并不意味着它实际上可以工作。事实上,你会发现相当大比例的序列实际上不能正常工作。你不能只使用LIst
测试代码,而不使用其他任何东西,然后假设它可以工作。@Servy:你是对的,所以我至少已经阻止了acce引发的异常正在处理不可用的泛型参数。在非泛型枚举上,将返回枚举类型本身。或者您知道获取所包含对象类型的方法(它可能会更改,例如在ArrayList中)?同意,@Servy-只是为了我在我的类中使用它的目的,目的非常简单-它只是在一个int数组上死了,这是一个问题,但是它永远不会被传递,即使是对象的数组@JohnBustos如果你知道代码被限制在一个非常小的对象集,那么你俩都应该指定t在您的问题中,不要询问任何任意的IEnumerable
,还要检查代码中的特定类型,以便代码能够正确地出错(带有有意义的错误消息)当提供任何其他类型时。不仅第一个项目可能与序列中的其他项目不属于同一类型,序列中可能没有项目,迭代序列可能代价高昂或产生副作用,或者可能不支持多次枚举,从而阻止任何实际的[有用]以后再使用对象。有很多方法会出错。当然可以,但我想如果你想获得序列中项目的类型信息,这是你能做的最好的方法
int[] paramValue = new int[] { 1, 2, 3 };
Type type = paramValue.GetType();
Type underlyingType;
if (type != typeof(string))
{
System.Collections.IEnumerable e = paramValue as System.Collections.IEnumerable;
if(e != null)
{
Type eType = e.GetType();
if(eType.IsGenericType)
{
underlyingType = eType.GetType().GetGenericArguments()[0];
}
else
{
foreach(var item in e)
{
underlyingType = item.GetType();
break;
}
}
}
}
object[] paramValue = new object[] { 1, "a", "c" };