如何获得IEnumerable的基类型

时间:2012-10-04 13:29:06

标签: c# ienumerable

  

可能重复:
  getting type T from IEnumerable<T>

我的房产类型为IEnumerable

public IEnumerable PossibleValues { get; set; }

如何发现实例的基本类型?

例如,如果它是这样创建的:

PossibleValues = new int?[] { 1, 2 }

我想知道类型是'int'。

3 个答案:

答案 0 :(得分:8)

Type GetBaseTypeOfEnumerable(IEnumerable enumerable)
{
    if (enumerable == null)
    {
        //you'll have to decide what to do in this case
    }

    var genericEnumerableInterface = enumerable
        .GetType()
        .GetInterfaces()
        .FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEnumerable<>));

    if (genericEnumerableInterface == null)
    {
        //If we're in this block, the type implements IEnumerable, but not IEnumerable<T>;
        //you'll have to decide what to do here.

        //Justin Harvey's (now deleted) answer suggested enumerating the 
        //enumerable and examining the type of its elements; this 
        //is a good idea, but keep in mind that you might have a
        //mixed collection.
    }

    var elementType = genericEnumerableInterface.GetGenericArguments()[0];
    return elementType.IsGenericType && elementType.GetGenericTypeDefinition() == typeof(Nullable<>)
        ? elementType.GetGenericArguments()[0]
        : elementType;
}

此示例有一些限制,可能会或可能不会影响您的应用程序。它不处理类型实现IEnumerable但不实现IEnumerable<T>的情况。如果类型多次实现IEnumerable<T>,它会任意选择一个实现。

答案 1 :(得分:3)

如果你想要PossibleValues的类型,你可以这样做:

var type = PossibleValues.GetType().ToString(); // "System.Nullable`1[System.Int32][]"

或者你可以这样做,如果你想要一个包含在PossibleValues中的项目类型(假设数组实际上有你问题中描述的值):

var type = PossibleValues.Cast<object>().First().GetType().ToString(); // "System.Int32"



修改

如果阵列可能不包含任何项目,那么你当然必须做一些空检查:

var firstItem = PossibleValues.Cast<object>().FirstOrDefault(o => o != null);
var type = string.Empty;
if (firstItem != null)
{
    type = firstItem.GetType().ToString();
}

答案 2 :(得分:2)

现有两种方法是查看对象是否实现IEnumerable<T>或检查集合中第一项的类型。第一个依赖于实际实现IEnumerable<T>的对象,第二个仅在序列中的所有项都具有相同派生类型时才有效。

您可能会问的一个有趣的问题是所有项目的共同类型,或者所有项目中最常见的最窄类型。

我们将从一个简单的帮助方法开始。给定一个类型,它将返回该类型的序列及其所有基类型。

public static IEnumerable<Type> getBaseTypes(Type type)
{
    yield return type;

    Type baseType = type.BaseType;
    while (baseType != null)
    {
        yield return baseType;
        baseType = baseType.BaseType;
    }
}

接下来,我们将有一个方法来获取序列的所有常见类型,方法是先找到所有派生类型,然后获取序列中每个Type的所有基类型,最后使用{{1只获取他们共有的那些项目:

intersect

请注意,第一种方法中类型的排序是从大多数派生到最少派生,而public static IEnumerable<Type> getCommonTypes(IEnumerable source) { HashSet<Type> types = new HashSet<Type>(); foreach (object item in source) { types.Add(item.GetType()); } return types.Select(t => getBaseTypes(t)) .Aggregate((a, b) => a.Intersect(b)); } 维护排序,因此生成的序列将按从大多数派生到最少派生的顺序排列。如果要查找所有这些类型共有的最窄类型,则只需对此方法的结果使用Intersect即可。 (请注意,由于所有内容都来自First,因此除非原始object中没有项目,否则此处至少会返回一种类型。