阻止集合操作和结构

时间:2013-07-12 07:37:42

标签: .net blockingcollection

我正在使用一个类型为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。这里的问题是结构不能为空,因此以下代码无效

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

因此阻塞集合仅限于类,还是语义更改返回非初始化结构?

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:0)

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

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

关于Take,正如Julien所说,Take抛出一个OperationCanceledException,它不返回null值。如果你想使用Take,你必须处理异常,无论你使用的是Struct还是Class。

更好的选择,特别是如果您希望频繁取消,则使用TryTake代替Take并检查结果。 e.g。

Struct myStruct;
if(collection.TryTake(out myStruct))
{
 ....
}