Я создал пользовательскую общую очередь, которая реализует общий интерфейс IQueue, который использует общую очередь из пространства имен System.Collections.Generic как частную внутреннюю очередь. Пример был очищен от нерелевантного кода.Если IEnumerable итератор в очереди деактивирует элемент
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();
...
}
}
Я хочу, чтобы держать вещи в соответствии с основными реализациями и заметили, что очереди ядро реализует 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, когда Dequeuing и нет элементов в очереди. Когда элемент помещается в очередь, появляется Monitor.Pulse. Это позволяет одному потоку подталкивать материал в очередь, а другой - «смотреть» очередь.
С точки зрения кодирования я пытаюсь решить, какой она выглядит чище:
foreach(QueueItem item in queue)
{
DoSomethingWithThe(item);
}
//Or
while(systemIsRunning)
{
DoSomethingWithThe(queue.Dequeue());
}
Для моей конкретной реализации это не имело бы значения, если бы было несколько элементов процесса извлечение из. Поскольку это очередь, они могут оба выбрать элемент, так как ни один элемент не должен обрабатываться более одного раза, следовательно, использование очереди.
EDIT
Интересно достаточно я нашел в блоге, где кто-то сделал именно это.
http://blogs.msdn.com/b/toub/archive/2006/04/12/blocking-queues.aspx
EDIT
Один последний удар в этом, прежде чем я закрыть это прочь. Как люди чувствуют, что класс не реализует IEnumerable, но имеет метод IEnumerator GetEnumerator(), который отменяет элементы? Язык .net поддерживает утиную печать, foreach является одним из видов использования. Возможно, это заслуживает собственного вопроса?
EDIT
поднял вопрос о реализации методы GetEnumerator без реализации IEnumerable в другом question.
Я согласен с тем, что я рассматривал, делая злоупотребления, поэтому причина для публикации, мне просто нужно было сказать 10 или 11 раз. Я думаю, что реальный вопрос, который я должен задать себе, - это почему мне нужно реализовать IEnumerable? Я делаю это, потому что основная реализация выполняется, поскольку у меня нет реальных требований для повторной итерации моей очереди. – Bronumski
К сожалению, я не могу отметить всех вас как правильно, поэтому я дам вам весь день, чтобы очистить ваши ответы и отметить наивысшее проголосовавшее как правильное. – Bronumski