5

我有一种情况,我得到一个对象,需要:

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

到目前为止我所拥有的。对 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);       
}

有人知道怎么做吗?

4

3 回答 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 中的通用变化

于 2013-02-20T16:24:04.270 回答
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如果你这样做,你会错过一些可以在 a 中使用的类型。可以用作 a 中的集合的对象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);
   }
}

在这种情况下,方法重载决策将根据对象是否为集合(在这种情况下由 implementation 定义IEnumerable<T>)为您选择正确的方法

于 2013-02-20T16:24:19.663 回答
0

使用以下代码:

Type t = typeof(System.Collections.IEnumerable);

Console.WriteLine(t.IsAssignableFrom(T)); //returns true for collentions
于 2013-02-20T16:31:27.133 回答