C# 自定义集合和继承的类类型

C# 自定义集合和继承的类类型,c#,inheritance,collections,C#,Inheritance,Collections,我有困难,可能错过了一些简单的东西,在集合中排队和取消排队 我有不同继承级别的类: public abstract class Item { //stuff } public class DetailItem : Item { //stuff } public class SuperDetailItem : DetailItem { //stuff } public class OddItem : Item { //stuff } 然后我有一个ConcurrentQueue如下:

我有困难,可能错过了一些简单的东西,在集合中排队和取消排队

我有不同继承级别的类:

public abstract class Item
{  //stuff }

public class DetailItem : Item
{  //stuff }

public class SuperDetailItem : DetailItem
{  //stuff }

public class OddItem : Item
{  //stuff }
然后我有一个
ConcurrentQueue
如下:

public class CQItems<Item> : ConcurrentQueue<Item>
{  //some methods }
Item item = GetItem();
DetailedItem detailedItem = item; // compilation error
并获取消息“无法从DetailItem转换为Item”

我不想为每个继承的类型创建特定的集合。我少了什么?谢谢

编辑:更新以获取更多信息。将
设置为
接口
并对其进行修复,以便在接口的第一个子项中定义通用方法,这并不能解决问题,甚至无法将集合设置为
IItem
类型的集合

我在这里添加了一些细节,以防我完全错误地处理这个问题。该软件是处理银行业务的其他软件的QA工具。项目可以是
Cash:Item
(或
IItem
)、
Check:Base
ReturnCheck:Check
和其他一些项目。每个子体都有一些其他子体不关心的类对象需要携带的附加信息。有些还需要其父类不需要的方法。这就是为什么我不想只使用一个包含所有元素的类和类型的
Enum
——不同的项需要以不同的方式进行验证和使用。例如,当
项目
是虚拟的,而不是界面时,它有一个字段
金额
。这是所有子孙后代永远拥有的唯一领域

在某些情况下,我希望collection类包含一些
CheckItem
对象和一些
CashItem
对象。在这些情况下,从队列中提取项目的代码将评估项目的类型并相应地处理它,并向调用函数提供适当的信息

目前,无论是
虚拟
还是
接口
实现,它都知道它是。。。a
检查项目
。但是由于基类没有“CheckNo”字段,当我只做
item.CheckNo
时,它表示
item
基类没有该字段(不,它没有)

目前,我通过以下方式使其工作:

IItem _item;
CheckItem item;

items.TryDequeue(out _item);
item = _item as CheckItem;

如果一次集合中只有一种类型的对象,这将非常好。这是我不能做的事情,还是我处理得不正确?

首先创建一个队列,该队列应该存储
元素

CQItems<Item> items = new CQItems<Item>();
TryDequeue
通过
out
修饰符“返回”一个
项。这与您尝试将
分配给
详细编辑项
的情况基本相同,如下所示:

public class CQItems<Item> : ConcurrentQueue<Item>
{  //some methods }
Item item = GetItem();
DetailedItem detailedItem = item; // compilation error
这显然毫无意义

TryDequeue
中的“Try”部分,不适用于铸件

您可能想做的是:

Item item;
items.TryDequeue(out item);
if (item is DetailItem)
{
    DetailItem detailedItem = (DetailItem) item;
    detailedItem.WhateverDetailedItemCanDo();
}
或者如果您使用的是C#7:


顺便说一句,这与“定制收藏”无关。如果使用
ConcurrentQueue
而不是
CQItems
,结果将是相同的。

您可以使集合协变或逆变,但不是不变的。你说wtf?我知道,你需要研究这些术语,你会发现为什么你不能做你想做的事情。协变正是我的目标,这就是为什么我使用ConcurrentQueue,它是基类。你不能。不是用C。当您将多个类型放入泛型集合时,它不再是1种类型的集合。因此,它就像一个arraylist.Hmmmm-有趣。更好的解决方案是问自己“您希望对集合中的这些项执行哪些常见操作”,并让您的所有项实现一个通用接口。创建该接口类型的集合。现在,您的通用集合是完全通用的。如果你必须将事物转换为一种特定的类型,这是设计缺陷的标志。我想也许我很难理解协方差和逆方差的应用方式。我假设我可以按照我想要的派生类类型(或者更确切地说,它是作为派生类创建的)将其抛出。然而,我不明白,将它作为一个项目出列并不能阻止它仍然是一个DetailItem。既然如此,我想这就是我所需要做的。我的主要目标是允许一个集合同时包含多个派生类型,如果可能的话,我想这将允许我这样做。@JesseWilliams你希望我在这个答案中添加什么吗?如果只是协方差和反方差,看看我对另一个问题的回答。它相当长,但应该有助于你“感受”它:
Item item;
items.TryDequeue(out item);
if (item is DetailItem)
{
    DetailItem detailedItem = (DetailItem) item;
    detailedItem.WhateverDetailedItemCanDo();
}
items.TryDequeue(out Item item);

if (item is DetailItem detailedItem)
{
    detailedItem.WhateverDetailedItemCanDo();
}