当我只能访问该列表的对象并且不知道类型参数时,如何迭代列表的项目?
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?
在我的代码中的某处,我有一个我已经知道的对象,它是一个列表。但我不知道该列表的类型参数。我需要遍历它的项目。我试图将该对象转换为对象列表,但它对我没有帮助:
List<Object> objList = (List<Object>)(dataModel.Value);
foreach (var item in objList)
{
Console.WriteLine(item.ToString());
}
在上面的代码中,dataModel
的Value
属性是一个XYZ
值的列表,但是当我运行时抛出异常这个代码。它说,它无法将 XYZ
转换为 Object
。
是否可以进行一些反序列化并在反序列化的对象上完成这项工作?
您应该转换为 IEnumerable<object>
,甚至只是 IEnumerable
。
A List<string>
不是 List<object>
,因为通用方差不适用于 类,并且 List<string>
不是 IList<object>
,因为 IList<T>
不是协变的。 (不可能,因为 接受 一个 T
的操作,例如 Add
。)
但是,IEnumerable<T>
在 T
中是协变的,这正是您在这种情况下想要的 - 但前提是您的值是 reference 的列表类型;协方差不适用于作为值类型的类型参数...因此 List<int>
无法转换为 IEnumerable<object>
。它 是 不过仍然可以转换为 IEnumerable
,所以下面的代码给了你最灵活的解决方案:
var items = (IEnumerable) dataModel.Value;
foreach (var item in items)
{
Console.WriteLine(item);
}
A List<Something>
不是从 List<object>
派生的,它是从 object
派生的,而不是从 List<object>
派生的,这是有道理的,因为它可能非常不安全。例如,您始终可以将 List<int>
视为 object
,但如果您可以将其视为 List<object>
,则可以调用 .Add("test")
并以 List<int>
包含 string
违反类型安全。
然而最近的 .net 版本增加了协变和逆变,它在 List<T>
上没有意义,但在 IEnumerable<T>
上确实有意义(因为你不能 "add"一个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.
在我的代码中的某处,我有一个我已经知道的对象,它是一个列表。但我不知道该列表的类型参数。我需要遍历它的项目。我试图将该对象转换为对象列表,但它对我没有帮助:
List<Object> objList = (List<Object>)(dataModel.Value);
foreach (var item in objList)
{
Console.WriteLine(item.ToString());
}
在上面的代码中,dataModel
的Value
属性是一个XYZ
值的列表,但是当我运行时抛出异常这个代码。它说,它无法将 XYZ
转换为 Object
。
是否可以进行一些反序列化并在反序列化的对象上完成这项工作?
您应该转换为 IEnumerable<object>
,甚至只是 IEnumerable
。
A List<string>
不是 List<object>
,因为通用方差不适用于 类,并且 List<string>
不是 IList<object>
,因为 IList<T>
不是协变的。 (不可能,因为 接受 一个 T
的操作,例如 Add
。)
但是,IEnumerable<T>
在 T
中是协变的,这正是您在这种情况下想要的 - 但前提是您的值是 reference 的列表类型;协方差不适用于作为值类型的类型参数...因此 List<int>
无法转换为 IEnumerable<object>
。它 是 不过仍然可以转换为 IEnumerable
,所以下面的代码给了你最灵活的解决方案:
var items = (IEnumerable) dataModel.Value;
foreach (var item in items)
{
Console.WriteLine(item);
}
A List<Something>
不是从 List<object>
派生的,它是从 object
派生的,而不是从 List<object>
派生的,这是有道理的,因为它可能非常不安全。例如,您始终可以将 List<int>
视为 object
,但如果您可以将其视为 List<object>
,则可以调用 .Add("test")
并以 List<int>
包含 string
违反类型安全。
然而最近的 .net 版本增加了协变和逆变,它在 List<T>
上没有意义,但在 IEnumerable<T>
上确实有意义(因为你不能 "add"一个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.