通用类列表的通用方法

时间:2017-08-24 09:50:40

标签: c# list class generics methods

我有问题。 例如,考虑这4个类。

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
{
}

如何编写一个接受任意ChildContainers的List作为参数的方法, 哪些操作在他们的fooLists上? 它甚至可能吗?

附加说明,ParentContainer有许多不同的子节点, 每个都有一个foo的不同孩子的列表。

public class ChildContainerB : ParentContainer<ChildFooB>{}
public class ChildContainerC : ParentCOntainer<ChildFooC>{}
...

public class ChildFooB : ParentFoo;
public class ChildFooC : ParentFoo;

然后我需要一个像这样的方法

//X means it can be any arbitrary ChildContainer
public void method(List<ChilContainerX> list) 
{
    foreach(ChildContainerX x in list)
    {
        print(x.fooList.Last().name);
    }
}

3 个答案:

答案 0 :(得分:1)

所以你问的是不可能的,因为你需要List<>的具体类型。但是有一些解决方法。

  1. 使用List<object>。这显然不是很好,因为这意味着你完全失去了类型检查,最终可能会添加到列表中的任何内容。因此,我不推荐这种方法。

  2. ParentContainer<>实现标记界面。例如:

    public interface IParentContainer
    {
    }
    
    public abstract class ParentContainer<T> : IParentContainer
        where T: ParentFoo
    {
        //snip
    }
    

    现在你可以这样列出:

    var containers = new List<IParentContainer>
    {
        new ChildContainer(),
        new ChildContainer2()
    };
    

答案 1 :(得分:0)

除非我误解了这个问题,否则你需要这样的东西......

public void DoStuffWith<T>(List<ParentContainer<T>> containers) where T : Parentfoo
{
     //TODO: implement
}

这适用于类型为...的对象

List<ParentContainer<ParentFoo>>
List<ParentContainer<ChildFoo>>

其中ChildFoo:ParentFoo

并解决了问题&#34; List<ParentContainer<ParentFoo>>没有实现IEnumerable<ParentContainer<ChuldFoo>>&#34;我怀疑是你看到的编译器。

更进一步,比如......

public void DoStuffWith<ContainerT,ElementT>(List<ContainerT<ElementT>> containers) 
  where ContainerT : ParentContainer 
  where ElementT : Parentfoo
{
     //TODO: implement
}

...可能使问题复杂化,但我怀疑你正在努力实现的目标。

此时我会质疑你拥有的数据结构,并给他们一些共同的父母,例如......

public class ParentContainer<T> : IEnumerable<T> { ... }
public class ChildContainer<T> : ParentContainer<T>, IEnumerable<T> { ... } 

由于两者都实现IEnumerable,你现在可以做...

public void DoStuffWith<T>(IEnumerable<T> containers) where T : ParentFoo
{
     //TODO: implement
}

这样就可以避免需要关注集合类型。

答案 2 :(得分:0)

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
    }
}