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

发布于 2024-11-19 22:50:02 字数 113 浏览 1 评论 0原文

我正在尝试编写一个通用的比较例程。但是,我的班级中的一些项目位于集合中,我需要枚举进行比较。

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

I am trying to write a generic comparison routine. However, some of the items in my class are in Collections and I need to enumerate to compare.

Is there an easy way, without a try/catch block to determine is a variable supports GetEnumerator()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

森林很绿却致人迷途 2024-11-26 22:50:03
if (object is IEnumerable)
{
    foreach(var value in (IEnumerable)object)
    {
        // ...
    }
}
if (object is IEnumerable)
{
    foreach(var value in (IEnumerable)object)
    {
        // ...
    }
}
静谧 2024-11-26 22:50:03

将其转换为 IEnumerable

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

Cast it into IEnumerable:

var list = someVariable as IEnumerable;
if (list != null)
{
    ...
}
一片旧的回忆 2024-11-26 22:50:03

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

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

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

The answers suggesting you check to see if the object is an IEnumerable are reasonably spot on. It's going to be the case the overwhelming majority of the time that your collection or object will implement that interface if it supports enumeration. But it is not required.

For something to be enumerated in a foreach, it really only needs to expose a GetEnumerator() method that returns an object with suitable MoveNext() and Current implementations. Consider something like:

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

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

    public int Current { get; private set; }
}

You can put new CustomCollection() into a loop and get the values 1..10.

By all means, check for the interface first. If that's all you want to support, fine. If you want to go that extra mile, you'd need to perform steps like the compiler would, as in check for the appropriate methods and return types. Here's a thoroughly untested draft of an implementation.

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;
}

Some quick tests in LinqPad, but by no means exhaustive...

IsEnumerable(new CustomCollection()).Dump(); // true
IsEnumerable(1).Dump(); // false 
IsEnumerable(new List<int>()).Dump(); // true
ペ泪落弦音 2024-11-26 22:50:03

GetEnumerator() 是在 IEnumerable 接口上定义的,因此:

if (obj is IEnumerable) 
{ 
   ... 
}

GetEnumerator() is defined on the IEnumerable interface, so:

if (obj is IEnumerable) 
{ 
   ... 
}
人生百味 2024-11-26 22:50:03

检查它是否实现了IEnumerableIEnumerable 派生自 IEnumerable,因此任何泛型集合也都实现 IEnumerable

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

Check if it implements IEnumerable. IEnumerable<T> derives from IEnumerable, so any generic collection implements IEnumerable too.

if you have a type you can use Type.IsAssignableFrom if you have an instance you can use the is/as operators.

你是年少的欢喜 2024-11-26 22:50:03

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

The IEnumerable interface determines whether or not something is enumerable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文