I'm having difficulty, probably missing something simple, with queuing and unqueuing items in a collection.
I have classes with various levels of inheritance:
public abstract class Item
{ //stuff }
public class DetailItem : Item
{ //stuff }
public class SuperDetailItem : DetailItem
{ //stuff }
public class OddItem : Item
{ //stuff }
I then have a ConcurrentQueue<T>
like so:
public class CQItems<Item> : ConcurrentQueue<Item>
{ //some methods }
One of the methods adds items when called, so I do something like:
CQItems<Item> items = new CQItems<Item>();
items.Generate(i);
It'll create i
items in the queue. This works, though currently in the method I am specifying creating DetailItem
items - I'd like to have that be dynamic if possible as well, but that'll be a different question. So later, I call to get a DetailItem
out like so:
DetailItem item;
items.TryDequeue(out item);
and get the message "Cannot convert from DetailItem to Item".
I don't want to make a specific collection for each inherited type. What piece am I missing? Thanks!
EDIT: Update for additional information. Making Item
an Interface
and fixing it so that common methods were defined in the first children of the interface didn't resolve the issue, even making the collection a collection of type IItem
.
I'm adding some details here in case I'm approaching this the wrong way entirely. The software is a QA tool for other software that deals with banking. Items can be Cash : Item
(or IItem
), Check: Base
, ReturnCheck : Check
and a handful of others. Each descendant has some additional information that the class object needs to carry around that the others do not care about. Some also require methods that their parent classes do not need. This is why I don't want to use just a single class with all of the elements and an Enum
for the type - different items will need to be validated differently and used differently. For instance, when Item
was virtual, rather than an interface, it had a field Amount
. It's the only field that ALL children and grandchildren will always have.
There will be some cases where I'd like to have the collection class contain some CheckItem
objects and some CashItem
objects. In those cases, the code that pulls items from the queue would evaluate the type of the item and work on it accordingly, as well as provide the appropriate information to the calling function.
Currently, with either the virtual
or interface
implementation, it KNOWS that it's say... a CheckItem
. But since the base class doesn't have a field for "CheckNo", when I just do item.CheckNo
, it says the Item
base class doesn't have that field (which no, it doesn't).
Currently I have it working by doing this:
IItem _item;
CheckItem item;
items.TryDequeue(out _item);
item = _item as CheckItem;
Which is great if there's only ever one type of object in the collection at a time. Is this something that I cannot do, or am I approaching it incorrectly?