将接收到的对象强制转换为List <object>或IEnumerable <object>


68

我正在尝试执行以下演员

private void MyMethod(object myObject)  
{  
    if(myObject is IEnumerable)  
    {
        List<object> collection = (List<object>)myObject;  
        ... do something   
    }  
    else  
    {  
        ... do something  
    }  
}

但是我总是以以下例外而告终:

无法转换类型为'System.Collections.Generic.List 1[MySpecificType]' to type 'System.Collections.Generic.List1 [System.Object]'的对象

我真的需要这样做,因为此方法必须非常通用才能接收未指定类型的单个对象和集合。

这可能吗,或者有另一种方法可以做到这一点。

谢谢。

Answers:


84

C#4将具有协变量和逆变量模板参数,但是在此之前,您必须做一些非通用的事情,例如

IList collection = (IList)myObject;

1
@Sergio,如果要避免运行时错误的风险,则应在强制转换之前检查myObject是否实现IList而不是IEnumerable。许多内置集合实现IEnumerable而不实现IList(例如,Dictionary <>,HashSet <>,Hashtable,Queue,Stack等)。
路加福音

@Luke:如果它是List <T>(问题暗示),它将实现IList。
erikkallen 2009年

1
@erikkallen,是的,但这是OP应该注意的事情。避免该问题只是在给定示例中将“ if(myObject is IEnumerable)”更改为“ if(myObject is IList)”的情况。
路加福音

或更简洁的说(如果使用IEnumerable),Items.As<IEnumerable>()?.Cast<object>() ?? Enumerable.Empty<object>()它表示:如果该通用对象列表实现IEnumerable且结果不为null,则将其作为对象列表获取。否则,只获取对象的空枚举。
詹姆斯M

68

您不能将IEnumerable <T>强制转换为List <T>。

但是您可以使用LINQ完成此操作:

var result = ((IEnumerable)myObject).Cast<object>().ToList();

2
这也在创建一个新列表,而不是强制转换原始列表。
卡梅隆·麦克法兰

我不得不使用(IEnumerable<object>)而不是仅仅使用(IEnumerable),否则可以正常工作。我使用dotnetcore 3.0
kkuilla

10

问题是,您正在尝试转换为更丰富的对象。您只需要将项目添加到新列表中:

if (myObject is IEnumerable)
{
   List<object> list = new List<object>();
   var enumerator = ((IEnumerable) myObject).GetEnumerator();
   while (enumerator.MoveNext())
   {
      list.Add(enumerator.Current);
   }
}

9

您实际上需要比普通用户IEnumerable提供更多的信息吗?只需将其投放并使用foreach它即可。在某些协议缓冲区中,我面临着完全相同的情况,并且我发现强制转换IEnumerable(或IList像列表一样访问它)的效果很好。




3

必须加入乐趣...

    private void TestBench()
    {
        // An object to test
        string[] stringEnumerable = new string[] { "Easy", "as", "Pi" };

        ObjectListFromUnknown(stringEnumerable);
    }

    private void ObjectListFromUnknown(object o)
    {
        if (typeof(IEnumerable<object>).IsAssignableFrom(o.GetType()))
        {
            List<object> listO = ((IEnumerable<object>)o).ToList();
            // Test it
            foreach (var v in listO)
            {
                Console.WriteLine(v);
            }
        }
    }

0

您需要像这样使用as运算符键入强制类型转换。

private void MyMethod(object myObject)  
{  
if(myObject is IEnumerable)  
{
    List<object> collection = myObject as(List<object>); 
    ... do something   
}  
else  
{  
    ... do something  
}  
}      

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.