चलिए एक और जवाब जोड़ते हैं। यह दूसरों पर क्यों?
1) सादगी। आकार की गारंटी देने की कोशिश अच्छी और अच्छी है लेकिन अनावश्यक जटिलता की ओर जाता है जो अपनी समस्याओं को प्रदर्शित कर सकता है।
2) इम्प्लिमेंट्स IReadOnlyCollection, जिसका अर्थ है कि आप इस पर Linq का उपयोग कर सकते हैं और इसे कई प्रकार की चीजों में पास कर सकते हैं जो IEnumerable की अपेक्षा करते हैं।
3) कोई लॉकिंग नहीं। ऊपर दिए गए कई समाधान ताले का उपयोग करते हैं, जो लॉकलेस संग्रह पर गलत है।
4) समान तरीकों का सेट, गुण, और इंटरफेस समवर्ती queue करता है, जिसमें IProducerConsumerCollection शामिल है, जो महत्वपूर्ण है यदि आप संग्रह के साथ ब्लॉकिंगकॉल का उपयोग करना चाहते हैं।
यदि ट्रिपडेक्यू विफल रहता है, तो यह कार्यान्वयन संभावित रूप से अधिक प्रविष्टियों के साथ समाप्त हो सकता है, लेकिन होने वाली आवृत्ति विशेष कोड के लायक नहीं लगती है जो अनिवार्य रूप से प्रदर्शन में बाधा डालती है और अपनी अप्रत्याशित समस्याओं का कारण बनती है।
यदि आप पूरी तरह से एक आकार की गारंटी देना चाहते हैं, तो प्रून () या इसी तरह की विधि को लागू करना सबसे अच्छा विचार है। आप अन्य तरीकों (TryDequeue सहित) में ReaderWriterLockSlim रीड लॉक का उपयोग कर सकते हैं और प्रूनिंग करते समय केवल एक राइट लॉक ले सकते हैं।
class ConcurrentFixedSizeQueue<T> : IProducerConsumerCollection<T>, IReadOnlyCollection<T>, ICollection {
readonly ConcurrentQueue<T> m_concurrentQueue;
readonly int m_maxSize;
public int Count => m_concurrentQueue.Count;
public bool IsEmpty => m_concurrentQueue.IsEmpty;
public ConcurrentFixedSizeQueue (int maxSize) : this(Array.Empty<T>(), maxSize) { }
public ConcurrentFixedSizeQueue (IEnumerable<T> initialCollection, int maxSize) {
if (initialCollection == null) {
throw new ArgumentNullException(nameof(initialCollection));
}
m_concurrentQueue = new ConcurrentQueue<T>(initialCollection);
m_maxSize = maxSize;
}
public void Enqueue (T item) {
m_concurrentQueue.Enqueue(item);
if (m_concurrentQueue.Count > m_maxSize) {
T result;
m_concurrentQueue.TryDequeue(out result);
}
}
public void TryPeek (out T result) => m_concurrentQueue.TryPeek(out result);
public bool TryDequeue (out T result) => m_concurrentQueue.TryDequeue(out result);
public void CopyTo (T[] array, int index) => m_concurrentQueue.CopyTo(array, index);
public T[] ToArray () => m_concurrentQueue.ToArray();
public IEnumerator<T> GetEnumerator () => m_concurrentQueue.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator () => GetEnumerator();
// Explicit ICollection implementations.
void ICollection.CopyTo (Array array, int index) => ((ICollection)m_concurrentQueue).CopyTo(array, index);
object ICollection.SyncRoot => ((ICollection) m_concurrentQueue).SyncRoot;
bool ICollection.IsSynchronized => ((ICollection) m_concurrentQueue).IsSynchronized;
// Explicit IProducerConsumerCollection<T> implementations.
bool IProducerConsumerCollection<T>.TryAdd (T item) => ((IProducerConsumerCollection<T>) m_concurrentQueue).TryAdd(item);
bool IProducerConsumerCollection<T>.TryTake (out T item) => ((IProducerConsumerCollection<T>) m_concurrentQueue).TryTake(out item);
public override int GetHashCode () => m_concurrentQueue.GetHashCode();
public override bool Equals (object obj) => m_concurrentQueue.Equals(obj);
public override string ToString () => m_concurrentQueue.ToString();
}