0

我正在使用具有 T 类型的类的 BlockingCollection,我想知道是否应该将 T 转换为结构。

从 BlockingCollection 签名原则上我看不出有什么问题:

[DebuggerDisplay("Count = {Count}, Type = {m_collection}")]
[ComVisible(false)]
[DebuggerTypeProxy(typeof (SystemThreadingCollections_BlockingCollectionDebugView<>))]
[HostProtection(SecurityAction.LinkDemand, ExternalThreading = true, Synchronization = true)]
public class BlockingCollection<T> : IEnumerable<T>, ICollection, IEnumerable, IDisposable

但是,支持取消的阻塞操作的语义是,如果在元素可用之前取消操作,则返回 null。这里的问题是一个结构不能为null,所以下面的代码是无效的

Struct myStruct = collection.Take(cancellationToken);
if(myStruct!=null) ... code

因此,阻塞集合是否仅限于类,或者语义更改是否返回未初始化的结构?

4

2 回答 2

2

根据文档,如果操作被取消,Take则不会返回:而是抛出 an 。随意使用任何类型,并准备好在需要时处理异常。nullOperationCanceledException

于 2013-07-12T07:44:41.023 回答
0

这更多地与结构与类的行为有关。不仅一个类不能为空,而且它也是按值传递的,而不是按引用传递的。这意味着每次访问集合中的元素时,您都会得到它的副本,而不是原始元素。

这对于所有集合都是一样的,而不仅仅是阻塞集合。

关于 Take,正如 Julien 所说,Take 会引发 OperationCanceledException,它不会返回 null 值。如果您想使用 Take,无论您使用 Struct 还是 Class,都必须处理异常。

一个更好的选择,特别是如果您期望频繁取消,是使用TryTake而不是 Take 并检查结果。例如

Struct myStruct;
if(collection.TryTake(out myStruct))
{
 ....
}
于 2013-07-12T07:46:12.570 回答