在C#中,可以确定变量是否具有枚举器

时间:2011-07-13 21:21:34

标签: c# enumeration

我正在尝试编写一个通用的比较例程。但是,我班上的一些项目都在收藏中,我需要枚举进行比较。

有没有一种简单的方法,没有try / catch块来确定变量是否支持GetEnumerator()

6 个答案:

答案 0 :(得分:4)

if (object is IEnumerable)
{
    foreach(var value in (IEnumerable)object)
    {
        // ...
    }
}

答案 1 :(得分:3)

将其投放到IEnumerable

var list = someVariable as IEnumerable;
if (list != null)
{
    ...
}

答案 2 :(得分:1)

GetEnumerator()IEnumerable界面上定义,因此:

if (obj is IEnumerable) 
{ 
   ... 
}

答案 3 :(得分:1)

建议您检查对象是否为IEnumerable的答案是合理的。绝大多数情况下,如果支持枚举,您的集合或对象将实现该接口。但这不是必需的。

对于foreach中要枚举的内容,它实际上只需要公开一个GetEnumerator()方法,该方法返回一个具有适当MoveNext()Current实现的对象。考虑类似的事情:

class CustomCollection
{
    public CustomEnumerator GetEnumerator()
    {
        return new CustomEnumerator();
    }
}

class CustomEnumerator
{
    public bool MoveNext()
    {
        return (++this.Current <= 10);
    }

    public int Current { get; private set; }
}

您可以将new CustomCollection()置于循环中并获取值1..10。

一定要先检查界面。如果这就是你想支持的全部,那很好。如果你想加倍努力,你需要像编译器一样执行步骤,如检查适当的方法和返回类型。这是一个完全未经测试的草案的实现。

bool IsEnumerable(object obj)
{
    if (obj is IEnumerable)
        return true;

    var info = obj.GetType().GetMethod("GetEnumerator");
    if (info != null)
    {
        if (info.ReturnType != null)
        {
            var moveNextMethod = info.ReturnType.GetMethod("MoveNext");
            if (moveNextMethod != null && moveNextMethod.ReturnType == typeof(bool))
            {
                var currentProperty = info.ReturnType.GetProperty("Current");
                if (currentProperty != null)
                    return true;
            }
        }
    }

    return false;
}

LinqPad中的一些快速测试,但并非详尽无遗......

IsEnumerable(new CustomCollection()).Dump(); // true
IsEnumerable(1).Dump(); // false 
IsEnumerable(new List<int>()).Dump(); // true

答案 4 :(得分:0)

检查它是否实现IEnumerableIEnumerable<T>派生自IEnumerable,因此任何通用集合也都会实现IEnumerable

如果您有类型,则可以使用Type.IsAssignableFrom如果您有实例,则可以使用is / as运算符。

答案 5 :(得分:0)

IEnumerable接口确定某些内容是否可枚举。