Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何检测T是否为IEnumerable<;T2>;,如果是这样,得到T2的类型?_C#_Generics_Reflection - Fatal编程技术网

C# 如何检测T是否为IEnumerable<;T2>;,如果是这样,得到T2的类型?

C# 如何检测T是否为IEnumerable<;T2>;,如果是这样,得到T2的类型?,c#,generics,reflection,C#,Generics,Reflection,我知道这个问题,它是后续的,也是一个,但我不能把它们放在一起,以帮助我做我想做的事情: 我有一个泛型类型,我想检查T是否是一个结构,或者如果它实现了IEnumerable,那么我想检查T2是否是一个结构 到目前为止,我已经到了这里('使用零碎的代码,这是实验性的): 私有类TestClass { 公共测试类() { 类型=类型(T); //(为清晰起见,检测T==IEnumerable ommitted) 类型enumerableType=Type.GetInterfaces() .Where(

我知道这个问题,它是后续的,也是一个,但我不能把它们放在一起,以帮助我做我想做的事情:

我有一个泛型类型,我想检查T是否是一个
结构
,或者如果它实现了
IEnumerable
,那么我想检查T2是否是一个
结构

到目前为止,我已经到了这里('使用零碎的代码,这是实验性的):

私有类TestClass
{
公共测试类()
{
类型=类型(T);
//(为清晰起见,检测T==IEnumerable ommitted)
类型enumerableType=Type.GetInterfaces()
.Where(t=>t.IsGenericType)
.Select(t=>t.GetGenericTypeDefinition())
其中(t=>t==typeof(IEnumerable))
.FirstOrDefault();
if(enumerableType!=null)
{
Type enumeratedType=Type.GetGenericArguments().First();
如果(!enumeratedType.IsValueType)//抛出等。。。
}
}
}
我遇到的问题是
enumerableType
IEnumerable
,因此
enumerableType
显示为
T
,而不是我传入的任何内容(例如
new TestClass()
)。

来自:

内部静态类类型系统{
内部静态类型GetElementType(类型seqType){
类型ienum=可查找可计算(seqType);
if(ienum==null)返回seqType;
返回ienum.GetGenericArguments()[0];
}
私有静态类型FindEnumerable(类型seqType){
if(seqType==null | | seqType==typeof(string))
返回null;
if(seqType.IsArray)
返回typeof(IEnumerable).MakeGenericType(seqType.GetElementType());
if(seqType.IsGenericType){
foreach(seqType.GetGenericArguments()中的类型arg){
类型ienum=typeof(IEnumerable);
if(ienum.IsAssignableFrom(seqType)){
回肠;
}
}
}
类型[]ifaces=seqType.GetInterfaces();
if(ifaces!=null&&ifaces.Length>0){
foreach(在ifaces中输入iface){
ienum类型=可计算的FindIEnumerable(iface);
如果(ienum!=null)返回ienum;
}
}
if(seqType.BaseType!=null&&seqType.BaseType!=typeof(对象)){
返回FindIEnumerable(seqType.BaseType);
}
返回null;
}
}

我相信这段代码可以满足您的要求。
不过你可能想把它清理一下

public class TestClass<T>
{
    public TestClass()
    {
        bool hasStruct = false;
        Type t1 = this.GetType().GetGenericArguments()[0];
        if(t1.IsValueType){
            hasStruct = true;
        }
        if (t1.IsGenericType)
        {
            Type t = t1.GetGenericArguments()[0];
            if (t.IsValueType)
            {
                hasStruct = true;
            }
        }

    }
}
公共类TestClass
{
公共测试类()
{
bool-hasStruct=false;
类型t1=this.GetType().GetGenericArguments()[0];
if(t1.IsValueType){
hasStruct=true;
}
if(t1.IsGenericType)
{
类型t=t1.GetGenericArguments()[0];
if(t.IsValueType)
{
hasStruct=true;
}
}
}
}

您的问题是,您选择了一个包含所有数据的类型,而选择了它的已擦除泛型类型模板

尝试:

Type enumerableType=Type.GetInterfaces()
.Where(t=>t.IsGenericType)
.Where(t=>t.GetGenericTypeDefinition()==typeof(IEnumerable))
.Select(t=>t.GetGenericArguments()[0])
.FirstOrDefault();

+1,所有其他答案都会犯与您没有的错误相同的错误,即
t==typeof(IEnumerable)
。这是行不通的,因为这种类型的实例永远不可能存在。@leppie,呃,谈到反射时,谈论类型的实例对我来说有点毛茸茸的。你是说你永远不能实例化类型为
IEnumerable
的对象,或者你永远不能拥有
typeof(T)==typeof(IEnumerable)
-就像在
typeof(IEnumerable
)中一样?@leppie:Look closer,GetGenericTypeDefinition()在比较之前被调用,它会匹配。@dtb:give for
Dictionary
?@BenVoigt,gives
System.Collections.Generic.KeyValuePair
2[System.Object,System.String]`对于meThanks,它是有效的,我相信你的边缘情况(在对dtb答案的评论中有点超出我的深度)。@Benjol:,您可能还需要显式检查数组,因为。dtb的测试是正确的<代码>如果(type.IsArray)返回type.GetElementType()
internal static class TypeSystem {
    internal static Type GetElementType(Type seqType) {
        Type ienum = FindIEnumerable(seqType);
        if (ienum == null) return seqType;
        return ienum.GetGenericArguments()[0];
    }
    private static Type FindIEnumerable(Type seqType) {
        if (seqType == null || seqType == typeof(string))
            return null;
        if (seqType.IsArray)
            return typeof(IEnumerable<>).MakeGenericType(seqType.GetElementType());
        if (seqType.IsGenericType) {
            foreach (Type arg in seqType.GetGenericArguments()) {
                Type ienum = typeof(IEnumerable<>).MakeGenericType(arg);
                if (ienum.IsAssignableFrom(seqType)) {
                    return ienum;
                }
            }
        }
        Type[] ifaces = seqType.GetInterfaces();
        if (ifaces != null && ifaces.Length > 0) {
            foreach (Type iface in ifaces) {
                Type ienum = FindIEnumerable(iface);
                if (ienum != null) return ienum;
            }
        }
        if (seqType.BaseType != null && seqType.BaseType != typeof(object)) {
            return FindIEnumerable(seqType.BaseType);
        }
        return null;
    }
}
public class TestClass<T>
{
    public TestClass()
    {
        bool hasStruct = false;
        Type t1 = this.GetType().GetGenericArguments()[0];
        if(t1.IsValueType){
            hasStruct = true;
        }
        if (t1.IsGenericType)
        {
            Type t = t1.GetGenericArguments()[0];
            if (t.IsValueType)
            {
                hasStruct = true;
            }
        }

    }
}
    Type enumerableType = type.GetInterfaces()
            .Where(t => t.IsGenericType)
            .Where(t => t.GetGenericTypeDefinition() == typeof(IEnumerable<>))
            .Select(t => t.GetGenericArguments()[0])
            .FirstOrDefault();