C#多种类型通用列表的通用列表

Chr*_*ris 12 c# generics

这是我的问题的抽象和简化:

我有一套玩具和相应的玩具箱.我希望用户能够指定盒子可以容纳的最大类型的玩具:

public class Box<T> {}
Run Code Online (Sandbox Code Playgroud)

然后在Box类中我想要一个通用的玩具列表,但是盒子中包含的每个玩具都有一个通用类型:

public class Box<T>
{
    public List<Toy> = new List<Toy>();
    public bool Whatever;

    [member functions, constructors...]
    [The member functions will depend on T]
}
Run Code Online (Sandbox Code Playgroud)

Toys类看起来像这样:

public class Toy<T> where T : struct //T is any type
{
    public List<T> = new List<T>();
    public string Name;
    public string Color;

    [member functions, constructors...]
}
Run Code Online (Sandbox Code Playgroud)

我希望能够创建具有许多不同类型的Toys,然后将它们插入到具有其他指定类型的Box中.然后我希望能够一起添加盒子,返回最大类型的盒子.

我真的不知道如何开始.具有多种类型的泛型类的列表实际上是让我循环.我阅读了有关使用抽象类或接口的各种文章,但没有找到一个例子或任何可以完成类似于我正在尝试的事情的东西.

任何人都可以提供任何帮助将非常感激.

解决方案可以在C#4.0中.

可能的未来澄清:

我希望Toy是通用的并且在实例化时接受一个参数,因为Toy还必须有一个List作为成员.

玩具中的嵌套列表是我的主要问题.然后我想要一个包含玩具的Box中的列表,但每个玩具都有不同的类型构造函数.

更新:

我把盒子固定在Box上,这是一个错字.

更新2:

Toy<plastic> tyPlastic = new Toy<plastic>("Name1", Blue, new plastic[] {0xFFEE00, 0xF34684, 0xAA35B2});
Toy<wood> tyWood = new Toy<wood>("Name2", Grain, new wood[] {a1, f4, h7});

Box<plastic> bxBox = new Box<plastic>();//The Box has the ability to hold both plastic and wood toys.  Plastic > Wood > Paper
Run Code Online (Sandbox Code Playgroud)

最后:我最终删除了Box为通用的要求.然后我用反射来创建动态类型的玩具.谢谢大家.

Eri*_*ert 27

如果能够很好地模拟现实,那么您正在构建的代码将被最好地理解.

模拟"A的B"的方法是使用泛型.一组可以容纳一种东西的盒子将被建模为Box<T>.一个只能装玩具的盒子Box<Toy>.一套可以容纳一种东西的盒子,那件东西必须是一个玩具Box<T> where T : Toy.

到现在为止还挺好.但是这个概念Toy<T>并没有映射到现实生活中的任何东西.你可能有一盒饼干或一盒玩具,但你没有饼干玩具,娃娃玩具或长颈鹿玩具."玩具"这个概念没有任何意义,所以不要模仿它.

建模的一个更明智的事情是"有一类通用的东西叫做玩具.没有一件东西只是玩具;每件玩具都是一种更具体的玩具.一个球就是玩具.一个玩偶就是一个玩偶.玩具." 所以建模:

abstract class Toy {}
class Doll : Toy {}
class Ball : Toy {}
Run Code Online (Sandbox Code Playgroud)

你说

我希望Toy是通用的并且在实例化时接受一个参数,因为Toy还必须有一个List作为成员.

为什么?玩具没有列出的东西.所以不要模仿那个.相反,盒子在逻辑上被建模为盒子内的玩具列表.(或者,由于盒子通常不适用订购,而盒子只包含独特的玩具,也许一套玩具会更好.)

我希望能够创建具有许多不同类型的Toys,然后将它们插入到具有其他指定类型的Box中.

好.所以一个操作Box<T>就是void Insert(T item).你可以将一个玩具放入一盒玩具中,你可以将一个玩偶放入一盒娃娃中,但你不能把球放入一盒娃娃中.

然后我希望能够一起添加盒子,返回最大类型的盒子.

您需要更仔细地定义"最大类型".如果你在一盒球上添加一盒娃娃,结果显然结果既不是一盒球也不是一盒娃娃.结果是一盒玩具.

以下是我对此进行建模的方法.我们已经拥有了玩具等级.我会继续说,一盒T被实现为一组内容,并提供一系列内容.

// Haven't actually compiled this.
class Box<T> : IEnumerable<T>
{
    private HashSet<T> set = new HashSet<T>();
    public Insert(T item) { set.Add(item); }
    public IEnumerator<T> GetEnumerator() { return set.GetEnumerator(); }
    public IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); }
Run Code Online (Sandbox Code Playgroud)

到目前为止一切都很无聊.现在我们来到有趣的位置.这只适用于C#4.

    public static Box<T> MergeBoxes(IEnumerable<T> box1, IEnumerable<T> box2)
    {
        Box<T> box = new Box<T>();
        foreach(T item in box1) box.Insert(item);
        foreach(T item in box2) box.Insert(item);
        return box;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在你可以说

Box<Doll> dollbox = new Box<Doll>() { new Doll() };
Box<Ball> ballbox = new Box<Ball>() { new Ball() };
Box<Toy> toybox2 = Box<Toy>.MergeBoxes(ballbox, dollbox);
Run Code Online (Sandbox Code Playgroud)

将一盒娃娃与一盒球合并的结果是一盒玩具.

最后一点只能起作用,因为IEnumerable<T>它在C#4中具有协变性.在C#3中,这样做起来会更加棘手; 你必须做类似的事情:

Box<Toy> toybox2 = Box<Toy>.MergeBoxes(ballbox.Cast<Toy>(), dollbox.Cast<Toy>());
Run Code Online (Sandbox Code Playgroud)

那有意义吗?

  • 他一开始就说这个例子是他的问题的抽象和简化。因此,他真正的问题很可能不涉及玩具和盒子,而是完全不同的东西。这可能只是一个(不是很好选择的)例子。 (2认同)