确定一个类型是否是枚举类型的通用列表。

3

我需要确定一个给定类型是否为枚举类型的泛型列表。

我想到了以下代码:

void Main()
{
    TestIfListOfEnum(typeof(int));
    TestIfListOfEnum(typeof(DayOfWeek[]));
    TestIfListOfEnum(typeof(List<int>));
    TestIfListOfEnum(typeof(List<DayOfWeek>));
    TestIfListOfEnum(typeof(List<DayOfWeek>));
    TestIfListOfEnum(typeof(IEnumerable<DayOfWeek>));
}

void TestIfListOfEnum(Type type)
{
    Console.WriteLine("Object Type: \"{0}\", List of Enum: {1}", type, IsListOfEnum(type));
}

bool IsListOfEnum(Type type)
{
    var itemInfo = type.GetProperty("Item");
    return (itemInfo != null) ? itemInfo.PropertyType.IsEnum : false;
}

以下是上述代码的输出结果:
Object Type: "System.Int32", List of Enum: False
Object Type: "System.DayOfWeek[]", List of Enum: False
Object Type: "System.Collections.Generic.List`1[System.Int32]", List of Enum: False
Object Type: "System.Collections.Generic.List`1[System.DayOfWeek]", List of Enum: True
Object Type: "System.Collections.Generic.List`1[System.DayOfWeek]", List of Enum: True
Object Type: "System.Collections.Generic.IEnumerable`1[System.DayOfWeek]", List of Enum: False

除了最后一个示例,所有输出都是我想要的。 它无法检测到typeof(IEnumerable<DayOfWeek>)是枚举类型的集合。

有人知道如何在这个最后的示例中检测枚举类型吗?


你混淆了 列表/集合/序列。看起来你想测试一组枚举的序列 - Lucas Trzesniewski
我不确定我理解自己为什么困惑。理想情况下,我希望能够在所有这些示例中检测到枚举类型。那就是我想要的。 - Jonathan Wood
IEnumerable<T> 是一个序列。ICollection<T> 是一个集合。IList<T> 是一个列表。这可能是吹毛求疵,但它与你的问题相关。 - Lucas Trzesniewski
@Mephy:不,我认为只需要枚举的集合就足够了。我不需要担心可能包含枚举的复杂类型。 - Jonathan Wood
@LucasTrzesniewski:这并不是挑剔。但它似乎没有直接回答问题。我猜如果我得不到答案,它给了我一些需要研究的领域。 - Jonathan Wood
不是为了回答问题,只是为了措辞,所以我说我在挑剔 ;) - Lucas Trzesniewski
3个回答

4
如果您想测试,给定一种类型,它是否为类型 IEnumerable<T>,其中 T 是枚举型变量,则可以执行以下操作。
首先,编写一个方法以获取可枚举对象所枚举的类型(s)。
    public static IEnumerable<Type> GetEnumerableTypes(Type type)
    {
        if (type.IsInterface)
        {
            if (type.IsGenericType
                && type.GetGenericTypeDefinition() == typeof(IEnumerable<>))
            {
                yield return type.GetGenericArguments()[0];
            }
        }
        foreach (Type intType in type.GetInterfaces())
        {
            if (intType.IsGenericType
                && intType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
            {
                yield return intType.GetGenericArguments()[0];
            }
        }
    }

然后:

    public static bool IsEnumerableOfEnum(Type type)
    {
        return GetEnumerableTypes(type).Any(t => t.IsEnum);
    }

实际上,这似乎也返回false。 - Jonathan Wood
@JonathanWood - 已找到并修复。 - dbc
@JonathanWood - 更新以处理类似于 public interface IBar : IEnumerable<int>, IEnumerable<DayOfWeek> { } 的情况。 - dbc

2
您可以像这样获取 IEnumerable<T> 的类型:
Type enumerableType = enumerable.GetType().GenericTypeArguments[0];

那么您可以通过检查该类型是否可分配给类型为 Enum 的变量来测试它是否是枚举,Enum 是枚举的基类:

typeof(Enum).IsAssignableFrom(enumerableType)

1
这里有一个简单的方法:
public static bool TestIfSequenceOfEnum(Type type)
{
    return (type.IsInterface ? new[] { type } : type.GetInterfaces())
        .Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEnumerable<>))
        .Any(i => i.GetGenericArguments().First().IsEnum);
}

基本上,提取类型实现的所有接口,查找所有IEnumerable<T>,如果其中任何一个T是枚举,则返回true。请记住,具体类可以多次实现IEnumerable<T>(具有不同的T)。
如果type是类或接口,都可以使用此方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接