Reputation: 3183
I'm trying to get a certain indexed item by number from a generic list and I'm getting: Unable to cast object of type 'System.Collections.Generic.List1[typename]' to type 'System.Collections.Generic.List
1[System.Object]'. errors.
What I'm trying to achieve is to loop (forward or backwards) to a certain list based upon a inherited baseclass; like so (or something similar anyway):
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>();
what I'd like to to is something like this:
public string[] BuildList(object GenericListHere, bool Backwards)
{
for(int i=GenericListHere.Length-1;i>=0;i--)
{
string MyName = GenericListHere[i].Name;
The above is somewhat pseudocoded, but I'd like to throw in either the apples or oranges list to get result. I don't know beforehand which object I'm getting, so I get the Count/Length like this (not psuedocoded) where TestObj is just the object I'm getting:
int iBound = -1;
try
{
System.Reflection.PropertyInfo oInfo = TestObj.GetType().GetProperty("Count");
iBound = (int)oInfo.GetValue(TestObj, null);
}
catch
{
And if the iBound >= 0 it's a collection. The next part.. I'm somewhat lost...
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];
What I'd really like is something like : VarCollection[iLoop], but that doesn't seem to work..
Anyone experienced with these kind of lists? TIA!
Upvotes: 1
Views: 385
Reputation: 113472
I really think reflection isn't the answer here; generics should be more than enough for your needs. It also appears that you don't actually need to access elements from the list by index since the intention appears to simply be to project a sequence of fruits to a sequence of fruit-names. If you do need to access elements by index however (e.g. if you stick with your for
loop), it shouldn't be an issue if you use generics; the indexer on IList<T>
as well as its Count
property is easily discoverable in generic code.
The following solution, which uses a generic constraint, should work fine in .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();
}
In .NET 4.0, a List<Apple>
is correctly recognized as anIEnumerable<Fruit>
. Consequently, the following signature should work too:
public static string[] BuildList(IEnumerable<Fruit> list, bool backwards)
On another note, you might want to consider returning an IEnumerable<string>
instead, and let the caller push the results into an array if it so desires.
Upvotes: 1
Reputation: 1064254
In the case where you are having to work with object
and reflection, you should probably simply use the non-generic IList
/ ICollection
interfaces rather than the generic IList<T>
/ ICollection<T>
/ List<T>
; you will still have indexer, iterate, add, etc
Upvotes: 0