In C #, is there a queue that can hold an object only once in its entire life?

I need a data structure, which is a special type of queue. I want that if an instance of my queue ever contained an object X, in this instance it would not be possible to re-put X in this instance. The enqueuing method should just do nothing if called with X, as an attempt to add a duplicate value to a HashSet.

Usage example:

MyQueue<int> queue = new MyQueue<int>(); 
queue.Enqueue(5); 
queue.Enqueue(17); 
queue.Enqueue(28); 
queue.Enqueue(17); 
int firstNumber = queue.Dequeue(); 
queue.Enqueue(5); 
queue.Enqueue(3); 

List<int> queueContents = queue.ToList(); //this list should contain {17, 28, 3}

I looked at MSDN but could not find such a class. Does this exist, or should I implement it myself?

, , FIFO, , . , , ​​ " ".

+4
4

- :

class UniqueQueue<T>
{
    private readonly Queue<T> queue = new Queue<T>();
    private HashSet<T> alreadyAdded = new HashSet<T>();

    public virtual void Enqueue(T item)
    {
        if (alreadyAdded.Add(item)) { queue.Enqueue(item); }
    }
    public int Count { get { return queue.Count; } }

    public virtual T Dequeue()
    {
        T item = queue.Dequeue();
        return item;
    }
}

. This Thread.

+4

.

, HashSet, .

, , HashSet , , .

, , , - HashSet.

+5

wayne answer, . ( Queue<T>)

sealed class UniqueQueue<T> : IEnumerable<T>, ICollection, IEnumerable
{
    private readonly Queue<T> queue;
    private readonly HashSet<T> alreadyAdded;

    public UniqueQueue(IEqualityComparer<T> comparer)
    {
        queue = new Queue<T>();
        alreadyAdded = new HashSet<T>(comparer);
    }

    public UniqueQueue(IEnumerable<T> collection, IEqualityComparer<T> comparer)
    {
        //Do this so the enumeration does not happen twice in case the enumerator behaves differently each enumeration.
        var localCopy = collection.ToList();

        queue = new Queue<T>(localCopy);
        alreadyAdded = new HashSet<T>(localCopy, comparer);
    }

    public UniqueQueue(int capacity, IEqualityComparer<T> comparer)
    {
        queue = new Queue<T>(capacity);
        alreadyAdded = new HashSet<T>(comparer);
    }

    //Here are the constructors that use the default comparer. By passing null in for the comparer it will just use the default one for the type.
    public UniqueQueue() : this((IEqualityComparer<T>) null) { }
    public UniqueQueue(IEnumerable<T> collection) : this(collection, null) { }
    public UniqueQueue(int capacity) : this(capacity, null) { }

    /// <summary>
    /// Attempts to enqueue a object, returns false if the object was ever added to the queue in the past.
    /// </summary>
    /// <param name="item">The item to enqueue</param>
    /// <returns>True if the object was successfully added, false if it was not</returns>
    public bool Enqueue(T item)
    {
        if (!alreadyAdded.Add(item))
            return false;

        queue.Enqueue(item);
        return true;
    }

    public int Count
    {
        get { return queue.Count; }
    }

    public T Dequeue()
    {
        return queue.Dequeue();
    }

    IEnumerator<T> IEnumerable<T>.GetEnumerator()
    {
        return ((IEnumerable<T>)queue).GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return ((IEnumerable)queue).GetEnumerator();
    }

    void ICollection.CopyTo(Array array, int index)
    {
        ((ICollection)queue).CopyTo(array, index);
    }

    bool ICollection.IsSynchronized
    {
        get { return ((ICollection)queue).IsSynchronized; }
    }

    object ICollection.SyncRoot
    {
        get { return ((ICollection)queue).SyncRoot; }
    }
}
+2

, Enqueue . hashset, :

public class UniqueValueQueue<T> : Queue<T>
{
    private readonly HashSet<T> pastValues = new HashSet<T>();

    public new void Enqueue(T item)
    {
        if (!pastValues.Contains(item))
        {
            pastValues.Add(item);

            base.Enqueue(item);
        }
    }
}

UniqueValueQueue<int> queue = new UniqueValueQueue<int>();
queue.Enqueue(5);
queue.Enqueue(17);
queue.Enqueue(28);
queue.Enqueue(17);
int firstNumber = queue.Dequeue();
queue.Enqueue(5);
queue.Enqueue(3);

List<int> queueContents = queue.ToList();

queueContents 17, 28 3.

0

All Articles