我正在使用一个类型为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
因此阻塞集合仅限于类,还是语义更改返回非初始化结构?
答案 0 :(得分:2)
根据documentation,Take
如果操作被取消,则不返回null
:而是抛出OperationCanceledException
。随意使用任何类型,并准备好在需要时处理异常。
答案 1 :(得分:0)
这更多地与结构与类的行为有关。这不仅是一个类不能为null,而且它也是通过值传递的,而不是通过引用传递的。这意味着每次访问集合的元素时,您都会获得它的副本而不是原始元素。
这对所有集合都是一样的,而不仅仅是阻塞集合。
关于Take,正如Julien所说,Take抛出一个OperationCanceledException,它不返回null值。如果你想使用Take,你必须处理异常,无论你使用的是Struct还是Class。
更好的选择,特别是如果您希望频繁取消,则使用TryTake代替Take并检查结果。 e.g。
Struct myStruct;
if(collection.TryTake(out myStruct))
{
....
}