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

これは、構造体とクラスの動作に関係しています。クラスを null にできないだけでなく、参照渡しではなく、値渡しでもあります。これは、コレクションの要素にアクセスするたびに、元の要素ではなくそのコピーを取得することを意味します。

これは、ブロッキング コレクションだけでなく、すべてのコレクションで同じです。

Take に関しては、Julien が指摘しているように、Take は OperationCanceledException をスローし、null 値を返しません。Take を使用する場合は、Struct を使用するか Class を使用するかに関係なく、例外を処理する必要があります。

特に頻繁にキャンセルされることが予想される場合は、Take の代わりにTryTakeを使用して結果を確認することをお勧めします。例えば

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