从genericlist获取索引项会引发错误

时间:2010-11-04 09:12:57

标签: c# list collections generics

我正在尝试从通用列表中按编号获取某个索引项目并且我得到:无法转换类型为'System.Collections.Generic.List 1[typename]' to type 'System.Collections.Generic.List的对象1 [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;

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

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

如果iBound&gt; = 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],但这似乎不起作用..

有这些名单的人吗? TIA!

3 个答案:

答案 0 :(得分:1)

我认为反思不是这里的答案;仿制药应该足以满足您的需求。您似乎还没有实际需要通过索引访问列表中的元素,因为意图似乎只是将一系列水果投影到一系列水果名称。如果您需要按索引访问元素(例如,如果您坚持使用for循环),那么如果您使用泛型则不应该是一个问题; IList<T>上的索引器及其Count属性在通用代码中很容易被发现。

以下使用通用约束的解决方案在.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<Apple>被正确识别为IEnumerable<Fruit>。因此,以下签名也应该起作用:

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

另一方面,您可能需要考虑返回IEnumerable<string>,并让调用者将结果推送到数组中,如果需要的话。

答案 1 :(得分:0)

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

答案 2 :(得分:0)

如果您必须使用object和反射,则应该只使用非通用IList / ICollection接口而不是通用{{1} } / IList<T> / ICollection<T>;你仍然会有索引器,迭代,添加等