Я создал настраиваемую универсальную очередь, которая реализует универсальный интерфейс IQueue, который использует универсальную очередь из пространства имен System.Collections.Generic в качестве частной внутренней очереди.Пример был очищен от ненужного кода.
public interface IQueue<TQueueItem>
{
void Enqueue(TQueueItem queueItem);
TQueueItem Dequeue();
}
public class CustomQueue<TQueueItem> : IQueue<TQueueItem>
{
private readonly Queue<TQueueItem> queue = new Queue<TQueueItem>();
...
public void Enqueue(TQueueItem queueItem)
{
...
queue.Enqueue( queueItem );
...
}
public TQueueItem Dequeue()
{
...
return queue.Dequeue();
...
}
}
Я хочу, чтобы все было согласовано с основными реализациями, и заметил, что ядро Queue реализует IEnumerable, поэтому я сделаю то же самое, явно реализовав IEnumerable в классе.или унаследовав его с помощью интерфейса IQueue.
Что я хочу знать, так это то, что при перечислении по очереди каждый из них должен перемещаться в следующий очередь из следующего элемента?Я использовал рефлектор, чтобы увидеть, как Microsoft сделала это, и все, что они делают, это перебирают приватный массив очередей, но Microsoft далеко не безошибочна, поэтому я хотел получить общее мнение.
public class CustomQueue<TQueueItem> : IQueue<TQueueItem>, IEnumerable<TQueueItem>
{
...
public IEnumerator<TQueueItem> GetEnumerator()
{
while (queue.Count > 0)
{
yield return Dequeue();
}
}
//Or
public IEnumerator<TQueueItem> GetEnumerator()
{
return queue.GetEnumerator();
}
...
}
Я попал в дваУмы, с одной стороны, я чувствую, что итерация по коллекции не должна изменять состояние коллекций, но с другой стороны, и особенно с моей конкретной реализацией, это сделало бы использование чистым.
EDIT
Чтобы поместить вещи в контекст.Класс, который я реализую, делает Monitor.Wait при снятии очереди, и в очереди нет элементов.Когда элемент помещается в очередь, появляется Monitor.Pulse.Это позволяет одному потоку помещать материал в очередь, а другой, по сути, «наблюдать» за ней.
С точки зрения кодирования я пытаюсь решить, какой из них выглядит чище:
foreach(QueueItem item in queue)
{
DoSomethingWithThe(item);
}
//Or
while(systemIsRunning)
{
DoSomethingWithThe(queue.Dequeue());
}
Для моей конкретной реализации не имело бы значения, если бы было несколько процессов, снимающих очереди.Поскольку это очередь, они оба могут выбрать элемент, поскольку ни один элемент не должен обрабатываться более одного раза, следовательно, используется очередь.
РЕДАКТИРОВАТЬ
Интересно, что я нашел сообщение в блогегде кто-то сделал именно это.
http://blogs.msdn.com/b/toub/archive/2006/04/12/blocking-queues.aspx
РЕДАКТИРОВАТЬ
Последний удар, прежде чем я закрою это.Как люди относятся к классу, не реализующему IEnumerable, но имеющему метод IEnumerator GetEnumerator (), который удаляет элементы?Язык .net поддерживает типизацию утиной утилитой, причем foreach является одним из вариантов использования.Возможно, это заслуживает отдельного вопроса?
EDIT
В другом вопросе
поставлен вопрос о реализации метода GetEnumerator без реализации IEnumerable *.