Reputation: 45
I have problem. For example, considering these 4 classes.
public abstract ParentContainer<T> where T: Parentfoo
{
public List<T> fooList;
}
//Let there be many different ChildContainers with different types.
public class ChildContainer : ParentContainer<ChildFoo>
{
}
public abstract class ParentFoo
{
public string name;
}
public class ChildFoo : ParentFoo
{
}
How can I write a method which accepts a List of any arbitrary ChildContainers as a parameter, which do operation on their fooLists? Is it even possible?
Additional Explanation, there are many different childs of ParentContainer, each with a List of a different child of foo.
public class ChildContainerB : ParentContainer<ChildFooB>{}
public class ChildContainerC : ParentCOntainer<ChildFooC>{}
...
public class ChildFooB : ParentFoo;
public class ChildFooC : ParentFoo;
Then I need a method something like this
//X means it can be any arbitrary ChildContainer
public void method(List<ChilContainerX> list)
{
foreach(ChildContainerX x in list)
{
print(x.fooList.Last().name);
}
}
Upvotes: 1
Views: 83
Reputation: 94
class Program
{
static void Main(string[] args)
{
List<ParentContainer<ChildFoo>> ca = new List<ParentContainer<ChildFoo>>();
ProcessContainers processor = new ProcessContainers();
ca.Add(new ChildContainerA { fooList = new List<ChildFoo>() });
ca.Add(new ChildContainerA { fooList = new List<ChildFoo>() });
ca.Add(new ChildContainerA { fooList = new List<ChildFoo>() });
ca.Add(new ChildContainerB { fooList = new List<ChildFoo>() });
processor.Process(ca);
}
}
public abstract class ParentContainer<T> where T: ParentFoo
{
public List<T> fooList;
}
//Let there be many different ChildContainers with different types.
public class ChildContainerA : ParentContainer<ChildFoo>
{
}
public class ChildContainerB : ParentContainer<ChildFoo>
{
}
public class ProcessContainers
{
public void Process<T>(List<ParentContainer<T>> childContainers) where T : ParentFoo
{
foreach(var item in childContainers)
{
foreach(var foo in item.fooList)
{
foo.Porcess();
}
}
}
}
public abstract class ParentFoo
{
public string name;
public abstract void Porcess();
}
public class ChildFoo : ParentFoo
{
public override void Porcess()
{
//Do some processing
}
}
Upvotes: 0
Reputation: 8628
Unless I misunderstand the question, you want something like this ...
public void DoStuffWith<T>(List<ParentContainer<T>> containers) where T : Parentfoo
{
//TODO: implement
}
This would work on objects of type ...
List<ParentContainer<ParentFoo>>
List<ParentContainer<ChildFoo>>
where ChildFoo : ParentFoo
and solves the issue of "List<ParentContainer<ParentFoo>>
does not implement IEnumerable<ParentContainer<ChuldFoo>>
" which I suspect is the compiler you are seeing.
Taking this a step further something like ....
public void DoStuffWith<ContainerT,ElementT>(List<ContainerT<ElementT>> containers)
where ContainerT : ParentContainer
where ElementT : Parentfoo
{
//TODO: implement
}
... likely over complicates the issue but i suspect is what you are trying to achieve.
At this point I would question the data structures you have and give them some common parent for example ...
public class ParentContainer<T> : IEnumerable<T> { ... }
public class ChildContainer<T> : ParentContainer<T>, IEnumerable<T> { ... }
Since both implement IEnumerable you can now do ...
public void DoStuffWith<T>(IEnumerable<T> containers) where T : ParentFoo
{
//TODO: implement
}
This avoids the need to be concerned with the collection type at all.
Upvotes: 0
Reputation: 119156
So what you are asking isn't possible because you need a concrete type for the List<>
. There are a couple of workarounds though.
Use List<object>
. This is obviously not great because as it means you lose type checking completely and could end up with anything being added to the list. So for that reason, I wouldn't recommend this approach.
Make ParentContainer<>
implement a marker interface. For example:
public interface IParentContainer
{
}
public abstract class ParentContainer<T> : IParentContainer
where T: ParentFoo
{
//snip
}
And now you can have your list like this:
var containers = new List<IParentContainer>
{
new ChildContainer(),
new ChildContainer2()
};
Upvotes: 1