I have a class A from which B and C inherit.
I have two lists: listB
and listC
, of the respective types.
I want to make a method that returns the two lists inside an array, like so:
public override List<A>[] GetAllItems()
{
return new List<A>[2]
{
listB,
listC
};
}
However, when I try this approach, I get the following error, because I try to convert the inherited types incorrectly.
Cannot implicitly convert type 'System.Collections.Generic.List<Lae.B>' to 'System.Collections.Generic.List<Lae.A>' [Assembly-CSharp]csharp(CS0029)
Is there some way to create this array without converting the elements?
Note: I am not using a struct or class, because I want the array to be of various sizes based on logic above.
CodePudding user response:
public List<A>[] GetAllItems()
{
var result = new List<A>[2] {
listB.Cast<A>().ToList(),
listC.Cast<A>().ToList(),
};
return result;
}
If you need to return array of List
s - easiest way is to use Cast
linq extension method.
In reference to the comments you have to remember that if you modify listB
or listC
, the change won't be reflected in the casted collections.
Anyway, if you need to have an access to the original listB
/ listC
collections references, you can use IEnumerable
instead of List
in order to not be forced to "materialize" the results. Example:
public IEnumerable<A>[] GetAllItems()
{
return new IEnumerable<A>[] {
listB,
listC,
};
}
Now when you access eg. allItems[0]
it will reference to the original listB
collection.
CodePudding user response:
You can't do that because instance of B is an also A but instance of List of B is not also List of A.
You should box the types in the collection, you can use Cast function of in the Linq namespace.
using System.Linq;
List<A>[] GetAllItems()
{
var result = new List<A>[2] {
listB.Cast<A>().ToList(),
listC.Cast<A>().ToList(),
};
return result;
}
Or you can do that manualy.
List<A>[] GetAllItems()
{
var boxedListB = new List<A>();
var boxedListC = new List<A>();
foreach (var item in listB)
{
boxedListB.Add(item);
}
foreach (var item in listC)
{
boxedListC.Add(item);
}
var result = new List<A>[2] {
boxedListB,
boxedListC
};
return result;
}
Or you can use Select function in System.Linq namespace.
List<A>[] GetAllItems()
{
var result = new List<A>[2] {
listB.Select(x=> x as A).ToList(),
listC.Select(x=>x as A).ToList()
};
return result;
}
You can check this document for more information about boxing/unboxing.