C# 检查传递的对象是否为IEnumerable<;T>;或单个值-包括T作为值类型

C# 检查传递的对象是否为IEnumerable<;T>;或单个值-包括T作为值类型,c#,generics,ienumerable,C#,Generics,Ienumerable,在我的C#代码的一部分中,我使用以下代码检查传入的对象是单个值还是实现了IEnumerable(T是字符串、双精度、int等,而不是复杂的对象或类): 它在所有情况下都工作得很好,直到今天,我传入了一个int[],我发现这是一个问题 那么,获取也包含值类型的IEnumerable的底层类型的最佳方法是什么 谢谢 一个IEnumerable没有底层类型,至少除了对象之外。您知道序列中的每个项都是一个对象,但您只知道这些。如果要处理所有项目都属于同一类型的项目序列(该类型不是object),则需要使

在我的C#代码的一部分中,我使用以下代码检查传入的对象是单个值还是实现了
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的依据是什么n
IEnumerable
实例?答案是对所问问题的有效答案;它实际上回答了所问的问题,而不是你希望他们会问但没有问的问题。如果问题说他们希望得到值的元素类型,而该值只能是数组或
列表,则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" };