Skip to content

Commit 8218ca8

Browse files
Adding TryDequeue method to Queue. Resolves #4316
1 parent f332ea1 commit 8218ca8

File tree

2 files changed

+105
-3
lines changed

2 files changed

+105
-3
lines changed

src/System.Collections/src/System/Collections/Generic/Queue.cs

+18-3
Original file line numberDiff line numberDiff line change
@@ -225,15 +225,30 @@ IEnumerator IEnumerable.GetEnumerator()
225225
// InvalidOperationException.
226226
public T Dequeue()
227227
{
228-
if (_size == 0)
228+
T removed;
229+
if (!TryDequeue(out removed))
229230
throw new InvalidOperationException(SR.InvalidOperation_EmptyQueue);
230231

231-
T removed = _array[_head];
232+
return removed;
233+
}
234+
235+
// Removes the object at the head of the queue and assigns to out parameter passed
236+
//if queue is not empty and returns true.
237+
// If the queue is empty, this method assigns default value to out parameter and returns false.
238+
public bool TryDequeue(out T item)
239+
{
240+
if (_size == 0)
241+
{
242+
item = default(T);
243+
return false;
244+
}
245+
246+
item = _array[_head];
232247
_array[_head] = default(T);
233248
MoveNext(ref _head);
234249
_size--;
235250
_version++;
236-
return removed;
251+
return true;
237252
}
238253

239254
// Returns the object at the head of the queue. The object remains in the

src/System.Collections/tests/Generic/Queue/Queue.Generic.Tests.cs

+87
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,93 @@ public void Queue_Generic_Constructor_int_Negative_ThrowsArgumentOutOfRangeExcep
9595

9696
#endregion
9797

98+
#region TryDequeue
99+
100+
[Fact]
101+
public void Queue_Generic_TryDequeue_OnEmptyQueue_ReturnsFalse()
102+
{
103+
T value;
104+
Assert.False(() => new Queue<T>().TryDequeue(out value));
105+
}
106+
107+
[Theory]
108+
[MemberData(nameof(ValidCollectionSizes))]
109+
public void Queue_Generic_TryDequeue_OnNonEmptyQueue_ReturnsTrue(int count)
110+
{
111+
Queue<T> q = GenericQueueFactory(count);
112+
T value;
113+
Assert.True(() => q.TryDequeue(out value));
114+
}
115+
116+
[Fact]
117+
public void Queue_Generic_TryDequeue_OnEmptyQueue_GivesDefaultValue()
118+
{
119+
T value;
120+
new Queue<T>().TryDequeue(out value);
121+
//Out argument has default value of T when queue is empty
122+
Assert.Equal(default(T), value);
123+
}
124+
125+
[Theory]
126+
[InlineData(0, 5)]
127+
[InlineData(1, 1)]
128+
[InlineData(3, 100)]
129+
public void Queue_Generic_TryDequeue_EnqueueTryDequeue(int capacity, int items)
130+
{
131+
int seed = 53134;
132+
T itemRemovedFromQueue;
133+
var q = new Queue<T>(capacity);
134+
Assert.Equal(0, q.Count);
135+
136+
// Enqueue some values and make sure the count is correct
137+
List<T> source = (List<T>)CreateEnumerable(EnumerableType.List, null, items, 0, 0);
138+
foreach (T val in source)
139+
{
140+
q.Enqueue(val);
141+
}
142+
Assert.Equal(source, q);
143+
144+
// Dequeue to make sure the values are removed in the right order and the count is updated
145+
for (int i = 0; i < items; i++)
146+
{
147+
T itemToRemove = source[0];
148+
source.RemoveAt(0);
149+
q.TryDequeue(out itemRemovedFromQueue);
150+
Assert.Equal(itemToRemove, itemRemovedFromQueue);
151+
Assert.Equal(items - i - 1, q.Count);
152+
}
153+
154+
// Can't dequeue when empty
155+
Assert.False(() => q.Dequeue(out itemRemovedFromQueue));
156+
157+
// But can still be used after a failure and after bouncing at empty
158+
T itemToAdd = CreateT(seed++);
159+
q.Enqueue(itemToAdd);
160+
q.TryDequeue(out itemRemovedFromQueue);
161+
Assert.Equal(itemToAdd, itemRemovedFromQueue);
162+
}
163+
164+
[Theory]
165+
[MemberData(nameof(ValidCollectionSizes))]
166+
public void Queue_Generic_TryDequeue_TryDequeueAfterClear(int count)
167+
{
168+
Queue<T> q = GenericQueueFactory(count);
169+
T value;
170+
//Can remove an item from non empty queue
171+
Assert.True(() => q.TryDequeue(out value));
172+
173+
//can't dequeue after clearing the queue
174+
q.Clear();
175+
Assert.False(() => q.TryDequeue(out value));
176+
177+
// But can still be used after a failure and after bouncing at empty
178+
T itemToAdd = CreateT(seed++);
179+
q.Enqueue(itemToAdd);
180+
Assert.True(() => q.TryDequeue(out value));
181+
}
182+
183+
#endregion
184+
98185
#region Dequeue
99186

100187
[Theory]

0 commit comments

Comments
 (0)