How to iterate over items of a list when I only have access to the object of that list and dont know the type parameter?

不羁岁月 提交于 2019-12-12 03:03:50

问题


Somewhere in my code I have an object that I already know that is a list. But I don't know the type parameter of that list. I need to iterate over it's items. I tried to cast that object to a list of objects but it didn't help me:

List<Object> objList = (List<Object>)(dataModel.Value);
foreach (var item in objList)
{
        Console.WriteLine(item.ToString());
}

In the above code, the Value property of dataModel is a list of XYZ values, but it throws an exception when I run this code. It says that, it could not cast XYZ to Object.

Is that possible to do some deserialization and do the job over deserialized objects?


回答1:


You should cast to IEnumerable<object>, or even just IEnumerable.

A List<string> is not a List<object> as generic variance doesn't apply to classes, and a List<string> is not an IList<object> as IList<T> is not covariant. (It can't be, due to operations which accept a T, such as Add.)

However, IEnumerable<T> is covariant in T which is exactly what you want in this case - but only if your value is a list of reference types; covariance doesn't work with type arguments which are value types... so a List<int> isn't convertible to IEnumerable<object>. It is still convertible to IEnumerable though, so the following code gives you the most flexible solution:

var items = (IEnumerable) dataModel.Value;
foreach (var item in items)
{
    Console.WriteLine(item);
}



回答2:


A List<Something> does not derive from List<object> it derives from object but not from List<object>, this makes sense as it could be very type unsafe. You can always treat a List<int> as an object for example, but if you could treat it as a List<object> you could then call .Add("test") and end up with a List<int> containing a string violating type safety.

However recent .net versions added covariance and contravariance, it doesn't make sense on List<T> but it DOES make sense on IEnumerable<T> (as you can't "add" to an IEnumerable but only enumerate it, it's very fine to enumerate items of arbitrary types as objects).

So you can cast to the interface:

IEnumerable<Object> objList = (IEnumerable<Object>)(dataModel.Value); // This works, List<whatever> is IEnumerable<whatever>, IEnumerable<whatever> can safely be cast to IEnumerable<object>

Or you can cast the individual items themselves if you want to stick to a List by creating a new List as such:

List<object> objlist = dataModel.Value
     .Cast<object>() // every item will be cast to object
     .ToList(); // then make a new list out of it, this is type safe as the original List<whatever> is not affected.


来源:https://stackoverflow.com/questions/34715706/how-to-iterate-over-items-of-a-list-when-i-only-have-access-to-the-object-of-tha

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!