Ignacio Soler Garcia
Ignacio Soler Garcia

Reputation: 21855

Cannot add new instance to generic list in generic class. Why?

I have the following generic class:

public class MessageProcesser<T> where T : Message

Inside the code I have the following attribute:

private readonly BlockingCollection<T> _messages;

When I try to do this I get an error (and as T is a Message it should be possible):

_messages.Add(new Message(MessageType.Stop));

What's wrong?

Thanks!

Upvotes: 2

Views: 173

Answers (2)

Adam Houldsworth
Adam Houldsworth

Reputation: 64517

The compiler error is the fact that you assume T is always Message. T could be a more derived type, like DerivedMessage : Message. This would make your collection BlockingCollection<DerivedMessage>, trying to set an instance of Message into this would be invalid.

If you want to contain a list of all messages regardless of type, all you need to do is have:

private readonly BlockingCollection<Message> _messages;

And completely remove the use of generics. You can then store Message types and any type that derives from Message.

If you want to have MessageProcessor<T> handle any message and store the correct, relevant type, you could always use the new() constraint that forces the type to have a public parameterless constructor:

public class MessageProcesser<T> where T : Message, new()

Then you can perhaps do this:

var message = new T(); 
message.MessageType = MessageType.Stop;
_messages.Add(message);

You cannot constrain on constructors with arguments, so your current constructor use would not be supportable. A way around this is to pass a MessageFactory to the MessageProcessor and abstract creation responsibility to the factory.

Upvotes: 3

Stefan Steinegger
Stefan Steinegger

Reputation: 64628

You don't have a collection of messages. Message can't be T, because T may have been inherited.

try

private readonly BlockingCollection<Message> _messages;

Upvotes: 4

Related Questions