【问题标题】:Get indexed item from genericlist throws error从 genericlist 获取索引项抛出错误
【发布时间】:2011-05-04 22:57:36
【问题描述】:

我正在尝试从通用列表中按编号获取某个索引项,但我得到:无法转换类型为“System.Collections.Generic.List1[typename]' to type 'System.Collections.Generic.List1[System.Object]”的对象。错误。

我想要实现的是基于继承的基类循环(向前或向后)到某个列表;像这样(或类似的东西):

public class Fruit
{
  public string Name {get;set;}
}
public class Apple : Fruit
{
  public bool IsSour {get;set;}
}
public class Orange : Fruit
{
  public bool Juicy {get;set;}
}
public List<Apple> Apples = new List<Apple>();
public List<Orange> Oranges = new List<Oranges>();

我想要的是这样的:

public string[] BuildList(object GenericListHere, bool Backwards)
{
  for(int i=GenericListHere.Length-1;i>=0;i--)
  {
    string MyName = GenericListHere[i].Name;

上面的代码有点伪代码,但我想输入苹果或橙子列表以获得结果。 我事先不知道我得到的是哪个对象,所以我得到了这样的计数/长度(不是伪编码),其中 TestObj 只是我得到的对象:

int iBound = -1;
try
{
    System.Reflection.PropertyInfo oInfo = TestObj.GetType().GetProperty("Count");
    iBound = (int)oInfo.GetValue(TestObj, null);
}
catch
{

如果 iBound >= 0 它是一个集合。下一部分..我有点迷路了......

 if (iBound != -1)
 {
      int iLoopStart = (backwardsLoop ? iBound - 1 : 0);
      int iLoopEnd = (backwardsLoop ? -1 : iBound);
      int iLoopDifference = (backwardsLoop ? -1 : +1);
      for (int iLoop = iLoopStart; iLoop != iLoopEnd; iLoop += iLoopDifference)
      {
           // THIS IS REALLY BAD CODED.. BUT I DONT GET IT
           object VarCollection = TestObj;
           object[] arInt = new object[1];
           arInt.SetValue(iLoop, 0);
           Type[] tArray = new Type[1];
           tArray.SetValue(typeof(int), 0);
           object oElem = ((System.Collections.Generic.List<object>)VarCollection)[iLoop];

我真正想要的是:VarCollection[iLoop],但这似乎不起作用..

有人对这类列表有经验吗?蒂亚!

【问题讨论】:

    标签: c# list collections generics


    【解决方案1】:

    我真的认为反思不是这里的答案;泛型应该足以满足您的需求。您似乎也实际上需要按索引访问列表中的元素,因为其意图似乎只是将水果序列投影到水果名称序列。但是,如果您确实需要通过索引访问元素(例如,如果您坚持使用 for 循环),那么使用泛型应该不是问题; IList&lt;T&gt; 及其 Countproperty 上的索引器很容易在通用代码中发现。

    以下使用通用约束的解决方案在 .NET 3.5 中应该可以正常工作:

    public static string[] BuildList<T>(IList<T> list, bool backwards) 
        where T : Fruit
    {
      var names = list.Select(fruit => fruit.Name);
      return (backwards ? names.Reverse() : names).ToArray();
    }
    

    在 .NET 4.0 中,List&lt;Apple&gt; 被正确识别为IEnumerable&lt;Fruit&gt;。因此,以下签名也应该起作用:

    public static string[] BuildList(IEnumerable<Fruit> list, bool backwards) 
    

    另一方面,您可能需要考虑返回 IEnumerable&lt;string&gt;,并让调用者根据需要将结果推送到数组中。

    【讨论】:

    • 这些名称是一个稍微简化的示例。我需要对对象本身做更多的事情,但我真的不知道我得到了什么列表。
    【解决方案2】:

    如果您必须使用object 和反射,您可能应该简单地使用非通用IList / ICollection 接口而不是通用IList&lt;T&gt; / ICollection&lt;T&gt; / @987654326 @;您仍将拥有索引器、迭代、添加等

    【讨论】:

    • 唉,我对此无话可说。我没有建立我要使用的对象的基础;我只是在传递对象时获取它们。
    • @riffnl - 但他们仍然 IList 等,无论他们如何描述自己。只需投射...
    【解决方案3】:

    只需将其转换为 IList 并使用索引器。

    【讨论】:

    • @riffnl:不,你没有。或者请解释您为什么会这样认为或假设。
    • “因为编译器这么说”可能是我的答案。但使用 System.Collections 似乎确实可以做到这一点。
    • @riffnl:呵呵,就像我对 Marc 评论的那样,人们忘记了非通用的基本实现。
    猜你喜欢
    • 1970-01-01
    • 2017-04-28
    • 1970-01-01
    • 2019-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-31
    • 1970-01-01
    相关资源
    最近更新 更多