当我只能访问该列表的对象并且不知道类型参数时,如何迭代列表的项目

本文关键字:列表 何迭代 项目 迭代 类型参数 访问 对象 不知道 | 更新日期: 2023-09-27 18:29:42

在我的代码中的某个地方,我有一个我已经知道的对象,它是一个列表。但我不知道该列表的类型参数。我需要迭代它的项目。我试图将该对象转换为对象列表,但它对我没有帮助:

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

在上面的代码中,dataModelValue 属性是XYZ值的列表,但是当我运行此代码时它会引发异常。它说,它不能XYZObject.

是否可以执行一些反序列化并对反序列化对象执行工作?

当我只能访问该列表的对象并且不知道类型参数时,如何迭代列表的项目

你应该投射到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")并最终得到包含违反类型安全性stringList<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.