Получить индексированный элемент из генериклика генерирует ошибку - PullRequest
1 голос
/ 04 ноября 2010

Я пытаюсь получить определенный индексированный элемент по номеру из общего списка, и я получаю: Невозможно привести объект типа '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> = 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], но, похоже, это не работает ..

Кто-нибудь сталкивался с подобными списками? ТИА!

Ответы [ 3 ]

1 голос
/ 04 ноября 2010

Я действительно думаю, что отражение здесь не является ответом; генериков должно быть более чем достаточно для ваших нужд. Также кажется, что вам на самом деле не нужно обращаться к элементам из списка по индексу, поскольку цель, по-видимому, состоит в том, чтобы просто проецировать последовательность фруктов на последовательность имен фруктов. Если вам действительно необходимо получить доступ к элементам по индексу (например, если вы придерживаетесь своего цикла 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> вместо этого и позволить вызывающему объекту поместить результаты в массив, если он того пожелает.

0 голосов
/ 04 ноября 2010

В случае, когда вам приходится работать с object и отражением, вам, вероятно, следует просто использовать неуниверсальные интерфейсы IList / ICollection вместо общих IList<T> / ICollection<T> / List<T>;у вас все еще будет индексатор, итерация, добавление и т. д.

0 голосов
/ 04 ноября 2010

Просто приведите его к IList и используйте индексатор.

...