当我只能访问该列表的对象并且不知道类型参数时,如何迭代列表的项目
本文关键字:列表 何迭代 项目 迭代 类型参数 访问 对象 不知道 | 更新日期: 2023-09-27 18:29:42
在我的代码中的某个地方,我有一个我已经知道的对象,它是一个列表。但我不知道该列表的类型参数。我需要迭代它的项目。我试图将该对象转换为对象列表,但它对我没有帮助:
List<Object> objList = (List<Object>)(dataModel.Value);
foreach (var item in objList)
{
Console.WriteLine(item.ToString());
}
在上面的代码中,dataModel
的 Value
属性是XYZ
值的列表,但是当我运行此代码时它会引发异常。它说,它不能XYZ
投Object
.
是否可以执行一些反序列化并对反序列化对象执行工作?
你应该投射到IEnumerable<object>
,甚至只是IEnumerable
。
List<string>
不是List<object>
,因为泛型方差不适用于类,而List<string>
不是IList<object>
因为IList<T>
不是协变。(不可能,因为操作接受T
,例如Add
。
但是,IEnumerable<T>
在T
中是协变的,在这种情况下这正是您想要的 - 但前提是您的值是引用类型的列表; 协方差不适用于值类型的类型参数......所以List<int>
不能转换为IEnumerable<object>
.不过,它仍然可以转换为IEnumerable
,因此以下代码为您提供了最灵活的解决方案:
var items = (IEnumerable) dataModel.Value;
foreach (var item in items)
{
Console.WriteLine(item);
}
List<Something>
不是从List<object>
派生出来的,而是从object
派生出来的,而不是从List<object>
派生出来的,这是有道理的,因为它可能非常不安全。例如,您始终可以将List<int>
视为object
,但如果可以将其视为List<object>
则可以调用.Add("test")
并最终得到包含违反类型安全性string
的List<int>
。
然而,最近的 .net 版本添加了协方差和逆变,它对List<T>
没有意义,但在IEnumerable<T>
上确实有意义(因为你不能"添加"到IEnumerable
而只能枚举它,枚举任意类型的项目是非常好的objects
(。
因此,您可以投射到接口:
IEnumerable<Object> objList = (IEnumerable<Object>)(dataModel.Value); // This works, List<whatever> is IEnumerable<whatever>, IEnumerable<whatever> can safely be cast to IEnumerable<object>
或者,如果您想通过创建新列表来强制转换单个项目本身:
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.