应在队列一个IEnumerable迭代器出列一个项目 [英] Should an IEnumerable iterator on a Queue dequeue an item

查看:197
本文介绍了应在队列一个IEnumerable迭代器出列一个项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建它实现了一个通用的IQueue接口,它采用了通用的队列从System.Collections.Generic命名空间为私有内部队列中的自定义通用的队列。实例已被清除不相关的code。

I have created a custom generic queue which implements a generic IQueue interface, which uses the generic Queue from the System.Collections.Generic namespace as a private inner queue. Example has been cleaned of irrelevant code.

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接口继承它。

I want to keep things consistent with the core implementations and have noticed that the core Queue implements IEnumerable so I will do the same either by explicitly implementing IEnumerable on the class or inheriting it with the IQueue interface.

我想知道的是?我已经使用反射来看看微软是如何做它,他们做的是通过队列私有数组一步,但微软还远远没有万无一失的,所以我希望得到一个普遍的看法。

What I want to know is when enumerating over the queue should each move next dequeue the next item? I have used reflector to see how Microsoft has done it and all they do is step through the queues private array but Microsoft is far from infallible so I wanted to get a general opinion.

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();
    }

    ...
}

我在两个头脑,一方面我觉得,通过集合迭代不应该改变的集合状态,但在另一方面,特别是与我的特定实现,将使得使用看起来很干净。

I am in two minds, on one hand I feel that iterating through a collection should not changed the collections state but on the other hand and especially with my particular implementation it would make the usage look clean.

修改

要把事情的来龙去脉。我正在实现的类不消除队列时Monitor.Wait,有队列中没有的项目。当一个项目被放置到队列中有一个Monitor.Pulse。这允许一个线程推东西到队列中,而另一个基本上监视的队列。

To put things into context. The class that I am implementing does a Monitor.Wait when Dequeuing and there are no items in the queue. When an item is put onto the queue there is a Monitor.Pulse. This allows for one thread to push stuff onto the queue and the other to essentially "watch" the queue.

从一个编码点,我试图决定它看起来更清洁的:

From a coding point of view I am trying to decide which it looks cleaner:

foreach(QueueItem item in queue)
{
    DoSomethingWithThe(item);
}

//Or

while(systemIsRunning)
{
    DoSomethingWithThe(queue.Dequeue());
}

有关我的具体执行也不会重要,如果有多个进程出队的项目。因为它是一个队列它们可以同时拾取一个项目,因为没有项目应该被处理一次以上,因此,使用一队列的

For my particular implementation it wouldn't matter if there were multiple process dequeuing items. Because it is a queue they can both pick of an item as no item should be processed more than once, hence the use of a queue.

修改

有趣的是我发现了一个博客帖子里有人做正是这一点。

Interestingly enough I have found a blog post where someone has done exactly this.

<一个href="http://blogs.msdn.com/b/toub/archive/2006/04/12/blocking-queues.aspx">http://blogs.msdn.com/b/toub/archive/2006/04/12/blocking-queues.aspx

修改

我关闭这个功能,在这方面的一个最后刺伤了。人们如何感受类没有实现IEnumerable,但有一个IEnumerator的GetEnumerator()方法,从队列的项目?在.NET语言支持鸭打字的foreach作为用途之一。这或许值得它自己的问题?

One last stab at this before I close this off. How do people feel about the class not implement IEnumerable but having an IEnumerator GetEnumerator() method that dequeues items? The .net language supports duck typing, foreach being one of the uses. Perhaps this deserves it's own question?

修改

没有在另一个实施了IEnumerable <一个都提出实现GetEnumerator方法的问题href="http://stackoverflow.com/questions/4194900/should-a-class-that-has-a-getenumerator-method-but-does-not-implement-ienumerable">question.

Have raised the question of implementing a GetEnumerator method without implementing IEnumerable in another question.

推荐答案

迭代器应始终幂,也就是,不修改队列为你迭代它。

Iterators should always be idempotent, that is, don't modify the queue as you iterate over it.

有没有保证不会有两个并行的迭代...

There are no guarantees that there won't be two concurrent iterations...

编辑,以解决新的注释:

Edit to address your new comments:

在其他编程器(如你的未来的自己;))出现时,以功能添加到code,它们可能无法假设迭代器是一次性使用的。他们可能只是用它(糟糕)之前添加,列出什么是在队列中的日志语句。

When another programmer (such as your future self ;) ) comes along to add features to the code, they may not assume that the iterators are single-use. They might add a log statement that lists what's in the queue just before using it (oops).

我只是想到另一件事是,Visual Studio调试器往往会列举你的类进行显示。这将导致一些极其混乱的错误:)

Another thing I just thought of is that the visual studio debugger will often enumerate your classes for display. That would cause some extremely confusing bugs :)

如果你实现了IEnumerable的子接口,并且不希望支持IEnumerable的,你应该引发NotSupportedException。虽然这不会给你任何编译时警告,运行时错误就会很清楚,而奇怪的IEnumerable的实现会浪费将来你小时。

If you're implementing a sub-interface of IEnumerable, and don't want to support IEnumerable, you should throw a NotSupportedException. Although this will not give you any compile time warnings, the run time error will be very clear, while a strange IEnumerable implementation could waste future you hours.

这篇关于应在队列一个IEnumerable迭代器出列一个项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆