草庐IT

C# Generic List of Multiple Types 泛型列表

coder 2024-05-26 原文

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

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

public class Box<T> {}

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

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

    [member functions, constructors...]
    [The member functions will depend on T]
}

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

我希望能够创建具有多种不同类型的 Toys,然后将它们插入具有另一种指定类型的 Box 中。然后我希望能够将盒子加在一起,返回最大类型的盒子。

我真的不知道如何开始。具有多种类型的泛型类的列表真的让我陷入困境。我阅读了各种关于使用抽象类或接口(interface)的文章,但没有找到一个示例或任何可以完成与我正在尝试做的事情类似的东西。

任何人都可以提供任何帮助,我们将不胜感激。

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

可能的 future 澄清:

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

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

更新:

我修复了 Box to 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

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

最佳答案

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

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

到目前为止一切顺利。但是Toy<T>的概念不映射到现实生活中的任何东西。您可能有一盒 cookies 或一盒玩具,但您没有 cookies 玩具、洋娃娃玩具或长颈鹿玩具。 “玩具”这个概念没有任何意义,所以不要模拟它

一个更明智的模型是“有一类叫做玩具的东西。没有任何东西只是玩具;每个玩具都是一种更具体的玩具。球是玩具。A娃娃是玩具。”所以建模:

abstract class Toy {}
class Doll : Toy {}
class Ball : Toy {}

你说

I want Toy to be generic and accept a argument at instantiation because Toy must also have a List as a member.

为什么? 玩具没有东西 list 。所以不要建模。相反,一个盒子在逻辑上被建模为盒子内玩具的列表。 (或者,由于一个盒子通常不应用排序,并且一个盒子只包含独特的玩具,也许一套玩具会更好。)

I want to be able to create Toys with many different types and then insert them into a Box with another specified type.

好的。所以对 Box<T> 进行操作是void Insert(T item) .你可以把一个玩具放进一盒玩具里,你可以把一个洋娃娃放进一盒洋娃娃里,但你不能把一个球放进一盒洋娃娃里。

Then I'd like to be able to add boxes together returning a Box with the largest type.

您需要更仔细地定义“最大类型”。如果将一盒洋娃娃加到一盒球上,显然结果既不是一盒球也不是一盒洋娃娃。结果是一盒玩具。

下面是我将如何对此进行建模。我们已经有了玩具层次结构。我会继续说,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(); }

到目前为止一切都很无聊。现在我们来到有趣的地方。 这只适用于 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;
    }
}

现在你可以说

Box<Doll> dollbox = new Box<Doll>() { new Doll() };
Box<Ball> ballbox = new Box<Ball>() { new Ball() };
Box<Toy> toybox2 = Box<Toy>.MergeBoxes(ballbox, dollbox);

将一盒玩偶与一盒球合并的结果是一盒玩具。

这最后一点只有效,因为 IEnumerable<T>在 C# 4 中是协变的。在 C# 3 中,要做到这一点会比较棘手;你必须做类似的事情:

Box<Toy> toybox2 = Box<Toy>.MergeBoxes(ballbox.Cast<Toy>(), dollbox.Cast<Toy>());

这有意义吗?

关于C# Generic List of Multiple Types 泛型列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2075866/

有关C# Generic List of Multiple Types 泛型列表的更多相关文章

  1. ruby - RVM 使用列表[0] - 2

    是否有类似“RVMuse1”或“RVMuselist[0]”之类的内容而不是键入整个版本号。在任何时候,我们都会看到一个可能包含5个或更多ruby的列表,我们可以轻松地键入一个数字而不是X.X.X。这也有助于rvmgemset。 最佳答案 这在RVM2.0中是可能的=>https://docs.google.com/document/d/1xW9GeEpLOWPcddDg_hOPvK4oeLxJmU3Q5FiCNT7nTAc/edit?usp=sharing-知道链接的任何人都可以发表评论

  2. Ruby on Rails regexp equals-tilde 与 array include 用于检查选项列表 - 2

    我正在使用Rails3.2.3和Ruby1.9.3p0。我发现我经常需要确定某个字符串是否出现在选项列表中。看来我可以使用Ruby数组.includemethod:或正则表达式equals-tildematchshorthand用竖线分隔选项:就性能而言,一个比另一个好吗?还有更好的方法吗? 最佳答案 总结:Array#include?包含String元素,在接受和拒绝输入时均胜出,对于您的示例只有三个可接受的值。对于要检查的更大的集合,看起来Set#include?和String元素可能会获胜。如何测试我们应该根据经验对此进行测试

  3. Ruby:如何将数组拼接成 Lisp 风格的列表? - 2

    这是我发现自己偶尔想做的事情。假设我有一个参数列表。在Lisp中,我可以像这样`(imaginary-function,@args)为了调用将数组从一个元素转换为正确数量的参数的函数。Ruby中是否有类似的功能?或者我只是在这里使用了一个完全错误的成语? 最佳答案 是的!它被称为splat运算符。a=[1,44]p(*a) 关于Ruby:如何将数组拼接成Lisp风格的列表?,我们在StackOverflow上找到一个类似的问题: https://stackov

  4. ruby-on-rails - Ruby on Rails 将列表拆分或切片为列 - 2

    @locations=Location.all#currentlistingall@locations=Location.slice(5)orLocation.split(5)使用Ruby,我试图将我的列表分成4列,每列限制为5个;然而,切片或拆分似乎都不起作用。知道我可能做错了什么吗?任何帮助是极大的赞赏。 最佳答案 您可能想使用in_groups_of:http://railscasts.com/episodes/28-in-groups-of这是RyanBates在railscast中的示例用法:

  5. Ruby 删除可枚举列表中的重复项 - 2

    ruby中有没有一个很好的方法来删除可枚举列表中的重复项(即拒绝等) 最佳答案 对于数组你可以使用uniq()方法a=["a","a","b","b","c"]a.uniq#=>["a","b","c"]所以如果你只是(1..10).to_a.uniq或%w{antbatcatant}.to_a.uniq因为无论如何,几乎所有您实现的方法都将作为Array类返回。 关于Ruby删除可枚举列表中的重复项,我们在StackOverflow上找到一个类似的问题: h

  6. ruby-on-rails - Scaffold Rails 3 View 中的外键下拉列表 - 2

    我使用脚手架和Rails3创建了2个模型。模型是位置和作业,每个作业都有一个位置。我在脚手架生成代码中创建了所需的引用调用,但是当我查看创建新作业的View时,我看到的只是一个文本框,我应该在其中添加location_id。我怎样才能让它变成下拉菜单以获得更好的用户体验? 最佳答案 想象一下,您有每个位置的titleAPI:http://apidock.com/rails/ActionView/Helpers/FormOptionsHelper/collection_select 关于r

  7. ruby - 如何在 Ruby 中创建数字列表并将其反向附加到它 - 2

    给定一个最小整数和最大整数,我想创建一个数组,它从最小值到最大值以二为单位计数,然后倒退(再次以二为单位,重复最大数)。例如,如果最小数是1,最大数是9,我想要[1,3,5,7,9,9,7,5,3,1].我试图尽可能简洁,这就是我使用单行代码的原因。在Python中,我会这样做:range(1,10,2)+range(9,0,-2)在我刚刚开始学习的Ruby中,到目前为止我所想到的是:(1..9).inject([]){|r,num|num%2==1?r这行得通,但我知道必须有更好的方法。这是什么? 最佳答案 (1..9).step

  8. ruby - Ruby 参数列表中的单个拼音/星号是什么意思? - 2

    这个问题在这里已经有了答案:nakedasteriskasparameterinmethoddefinition:deff(*)(1个回答)关闭9年前。我今天浏览了Rails3ActiveRecord源代码,发现amethodwheretheentireparameterlistwasasingleasterisk.defsave(*)我找不到很好的描述来说明它的作用(尽管我有一些基于我对splat参数的了解的想法)。它有什么作用,为什么要使用它?

  9. ruby - 在 ruby​​ 中合并两个排序列表的内置方法 - 2

    我有两个Foo对象列表。每个Foo对象都有一个时间戳,Foo.timestamp。两个列表最初都按时间戳降序排列。我想以最终列表也按时间戳降序排序的方式合并Foo对象的两个列表。实现这个并不难,但我想知道是否有任何内置的Ruby方法可以做到这一点,因为我认为内置方法会产生最佳性能。谢谢。 最佳答案 这会起作用,但不会提供很好的性能,因为它不会利用事先已经排序的列表:list=(list1+list2).sort_by(&:timestamp)我不知道有任何内置函数可以满足您的需求。 关于

  10. ruby - 从列表中生成从 n 到 m 的数字 - 2

    我将从一个例子开始;给定n=1和m=100以及一个列表[1,2,3]生成所有包含一位数和两位数的数字等等,但在这种情况下它们需要小于100。输出:-1,2,3,11,12,13,21,22,23,31,32,33然后我们停止,因为下一个数字将超过100,例如:-111,112,113,121,122,123,131,132,133,21..,.22...,23...,31,32,33正如您所注意到的,我将1,2,3,4附加到之前创建的数字,为此我使用了一个递归函数,该函数在for循环中为我的列表,它们会一直运行,直到生成的数字大于我的限制。defx(str,finish,d,c)ret

随机推荐