【问题标题】: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?当我只能访问该列表的对象并且不知道类型参数时,如何迭代列表的项目?
【发布时间】:2016-01-11 06:53:56
【问题描述】:

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

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

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

是否可以进行一些反序列化并在反序列化的对象上完成这项工作?

【问题讨论】:

  • dataModel.Value 的类型是什么?
  • 发送至IEnumerable&lt;Object&gt;是否有效?
  • stackoverflow.com/questions/632570/… 怎么样?尝试使用IList
  • 你为什么要投?? foreach (object item in dataModel.Value) 应该可以正常工作,不是吗?
  • @FrebinFrancis dataModel.Value 是一个列表。但我不知道该列表中的项目类型。

标签: c# .net generic-list


【解决方案1】:

你应该投给IEnumerable&lt;object&gt;,甚至只是IEnumerable

List&lt;string&gt; 不是List&lt;object&gt;,因为通用方差不适用于类,List&lt;string&gt; 不是IList&lt;object&gt;,因为IList&lt;T&gt; 不是协变的。 (不可能,因为操作接受T,例如Add。)

但是,IEnumerable&lt;T&gt;T 中是协变的,这正是您在这种情况下想要的 - 但前提是您的值是 reference 类型的列表;协方差不适用于作为值类型的类型参数......所以List&lt;int&gt; 不能转换为IEnumerable&lt;object&gt; 仍然可以转换为 IEnumerable,因此以下代码为您提供了最灵活的解决方案:

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

【讨论】:

    【解决方案2】:

    List&lt;Something&gt; 不是从 List&lt;object&gt; 派生的,它是从 object 派生的,但不是从 List&lt;object&gt; 派生的,这是有道理的,因为它可能是非常不安全的类型。例如,您始终可以将List&lt;int&gt; 视为object,但如果您可以将其视为List&lt;object&gt;,则可以调用.Add("test") 并最终得到包含stringList&lt;int&gt; 违反类型安全.

    然而最近的 .net 版本增加了协变和逆变,它在 List&lt;T&gt; 上没有意义,但在 IEnumerable&lt;T&gt; 上确实有意义(因为你不能“添加”到 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.
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-04
      • 2023-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-20
      • 1970-01-01
      相关资源
      最近更新 更多