【问题标题】:Cannot add new instance to generic list in generic class. Why?无法将新实例添加到泛型类的泛型列表中。为什么?
【发布时间】:2012-06-14 07:46:38
【问题描述】:

我有以下通用类:

public class MessageProcesser<T> where T : Message

在代码中我有以下属性:

private readonly BlockingCollection<T> _messages;

当我尝试这样做时,我得到一个错误(因为 T 是一条消息,它应该是可能的):

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

怎么了?

谢谢!

【问题讨论】:

  • 为什么需要泛型?

标签: c# .net generics constraints


【解决方案1】:

您没有消息集合。消息不能是 T,因为 T 可能已被继承。

试试

private readonly BlockingCollection<Message> _messages;

【讨论】:

  • +1 事实上,换一种说法,虽然 OP 声明 where T : MessageT 可能是 DerivedMessage : Message,因此将 Message 添加到 BlockingCollection&lt;DerivedMessage&gt; 是无效的。但是,将 DerivedMessage 添加到 BlockingCollection&lt;Message&gt; 是有效的,并且可能是 OP 正在尝试做的事情。
  • 谢谢,你是对的。 MessageProcessor 应该处理 Messages,而不是 T。
【解决方案2】:

编译器错误是您假设T 始终为MessageT 可以是更多派生的类型,例如DerivedMessage : Message。这将使您的收藏集BlockingCollection&lt;DerivedMessage&gt;,尝试将Message 的实例设置为无效。

如果您想包含所有类型的所有消息的列表,您需要做的就是:

private readonly BlockingCollection<Message> _messages;

并彻底删除泛型的使用。然后,您可以存储 Message 类型和派生自 Message 的任何类型。

如果您想让MessageProcessor&lt;T&gt; 处理任何消息并存储正确的相关 类型,您始终可以使用new() 约束来强制该类型具有public 无参数 构造函数:

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

那么你也许可以这样做:

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

不能使用参数约束构造函数,因此您当前的构造函数使用将不受支持。解决此问题的一种方法是将MessageFactory 传递给MessageProcessor 并将abstract 创建责任传递给工厂。

【讨论】:

  • 我也可以接受你的回答......另一个在页面上更高:P
  • @SoMoS 完全由你决定,我没有大惊小怪 :-) 我只是想用更多细节来补充他的回答。
猜你喜欢
  • 2013-11-27
  • 2019-03-12
  • 1970-01-01
  • 2016-07-03
  • 2010-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-07
相关资源
最近更新 更多