将对象转换为集合

5

我有这样一个情况,我被给予了一个对象,并需要做以下事情:

  • 确定该对象是单个对象还是集合(Array、List等)
  • 如果它是一个集合,则遍历该列表。

到目前为止,我所拥有的并不能测试IEnumerable。而且将其转换为IEnumerable只适用于非基元类型。

static bool IsIEnum<T>(T x)
{
    return null != typeof(T).GetInterface("IEnumerable`1");
}
static void print(object o)
{
    Console.WriteLine(IsIEnum(o));       // Always returns false
    var o2 = (IEnumerable<object>)o;     // Exception on arrays of primitives
    foreach(var i in o2) {
        Console.WriteLine(i);
    }
}
public void Test()
{
    //int [] x = new int[]{1,2,3,4,5,6,7,8,9};
    string [] x = new string[]{"Now", "is", "the", "time..."};
    print(x);       
}

有人知道如何做到这一点吗?

3
如果你已经有了泛型,为什么还要使用 object?为什么不使用 print<T>(T obj)?此外,你尝试过使用 is IEnumerable 替代 GetInterface 吗?对于运行时检查,你不应该使用 typeof,而是应该使用 GetType。 - It'sNotALie.
谢谢大家。我使用了 Snippet Compiler 进行测试,但没有注意到它默认使用了 "using System.Collections.Generic;"。我曾尝试过非泛型的 IEnumerable,但直到我改为 "using System.Collections" 后才消除了错误。 - 001
3个回答

10

只需要检查对象是否可转换为非泛型的IEnumerable接口:

var collection = o as IEnumerable;
if (collection != null)
{
    // It's enumerable...
    foreach (var item in collection)
    {
        // Static type of item is System.Object.
        // Runtime type of item can be anything.
        Console.WriteLine(item);
    }
}
else
{
    // It's not enumerable...
}

IEnumerable<T> 实现了 IEnumerable 接口,因此这将适用于通用和非通用类型。使用此接口而不是通用接口可以避免通用接口变异的问题: IEnumerable<T> 不一定可转换为 IEnumerable<object>

本问题在C# 4.0中的通用变化中有更详细的讨论。


0

不要使用通用版本的 IEnumerable

static void print(object o)
{
    Console.WriteLine(IsIEnum(o));       // Always returns false
    var o2 = o as IEnumerable;     // Exception on arrays of primitives
    if(o2 != null) {
      foreach(var i in o2) {
        Console.WriteLine(i);
      }
    } 
}

如果你按照这种方式做,可能会错过一些可以在foreach中使用的类型。可用作foreach集合的对象不需要实现IEnumerable接口,它只需要实现GetEnumerator方法,该方法需要返回一个具有Current属性和MoveNext方法的类型。

如果集合是有类型的,而你只需要支持不同种类的集合,你可以这样做:

static void print<T>(T o) {
    //Not a collection
}

static void print<T>(IEnumerable<T> o) {
   foreach(var i in o2) {
        Console.WriteLine(i);
   }
}

在这种情况下,方法重载解析将根据对象是否为集合(在此情况下通过实现 IEnumerable<T> 定义)为您选择正确的方法。

0
请使用以下代码:
Type t = typeof(System.Collections.IEnumerable);

Console.WriteLine(t.IsAssignableFrom(T)); //returns true for collentions

1
字符串也实现了 IEnumerable,因此您需要将字符串过滤掉。 - Sam

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