为什么队列(T)和堆栈(T)未实现的ICollection(T)? [英] Why do Queue(T) and Stack(T) not implement ICollection(T)?

查看:190
本文介绍了为什么队列(T)和堆栈(T)未实现的ICollection(T)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我甚至问,让我得到了明显的答案出路:的ICollection< T> 接口包括删除方法来删除任意元素,其中问答LT; T> 堆栈< T> 不能真正支持(因为它们只能删除结束元素)。

Before I even ask, let me get the obvious answer out of the way: The ICollection<T> interface includes a Remove method to remove an arbitrary element, which Queue<T> and Stack<T> can't really support (since they can only remove "end" elements).

OK,我意识到这一点。其实,我的问题是没有专门关于问答LT; T&GT; 堆栈&LT; T&GT; 集合类型;相反,它是关于不实施的ICollection&LT的设计决定; T&GT; 任何的泛型类型,它本质上是的集合牛逼值。

OK, I realize that. Actually, my question is not specifically about the Queue<T> or Stack<T> collection types; rather, it's about the design decision of not implementing ICollection<T> for any generic type that is essentially a collection of T values.

下面是我觉得奇怪。说我有接受任意集合的方法 T ,和的code我写这将是有益知道的大小目的采集。例如(以下code是微不足道的,只用于说明!):

Here's what I find odd. Say I have a method that accepts an arbitrary collection of T, and for the purpose of the code I'm writing it would be useful to know the size of the collection. For example (the below code is trivial, for illustration only!):

// Argument validation omitted for brevity.
static IEnumerable<T> FirstHalf<T>(this ICollection<T> source)
{
    int i = 0;
    foreach (T item in source)
    {
        yield return item;
        if ((++i) >= (source.Count / 2))
        {
            break;
        }
    }
}

现在,实在没有理由这样code不能在问答其中操作; T&GT; 堆栈&LT; T&GT; ,除了这些类型不落实的ICollection&LT; T&GT; 。他们的执行的实施的ICollection ,当然 - 我猜主要为计数属性孤独,但是,导致怪异的优化code是这样的:

Now, there's really no reason why this code couldn't operate on a Queue<T> or a Stack<T>, except that those types don't implement ICollection<T>. They do implement ICollection, of course—I'm guessing mainly for the Count property alone—but that leads to weird optimization code like this:

// OK, so to accommodate those bastard Queue<T> and Stack<T> types,
// we will just accept any IEnumerable<T>...
static IEnumerable<T> FirstHalf<T>(this IEnumerable<T> source)
{
    int count = CountQuickly<T>(source);
    /* ... */
}

// Then, assuming we've got a collection type with a Count property,
// we'll use that...
static int CountQuickly<T>(IEnumerable collection)
{
    // Note: I realize this is basically what Enumerable.Count already does
    // (minus the exception); I am just including it for clarity.
    var genericColl = collection as ICollection<T>;
    if (genericColl != null)
    {
        return genericColl.Count;
    }

    var nonGenericColl = collection as ICollection;
    if (nonGenericColl != null)
    {
        return nonGenericColl.Count;
    }

    // ...or else we'll just throw an exception, since this collection
    // can't be counted quickly.
    throw new ArgumentException("Cannot count this collection quickly!");
}

那岂不是更有意义只是完全放弃的ICollection 接口(我的意思不是下降过程的实施,因为这将是一个重大更改,我只是说,停止使用),并简单地实施的ICollection&LT; T&GT; 有明确实现成员没有一个完美的匹配?

Wouldn't it make more sense to just abandon the ICollection interface completely (I don't mean drop the implementation, of course, as that would be a breaking change; I just mean, stop using it), and simply implement ICollection<T> with explicit implementation for members that don't have a perfect match?

我的意思是,看看的ICollection&LT; T&GT; 提供:

I mean, look at what ICollection<T> offers:

  • 计数 - 问答LT; T&GT; 堆栈&LT; T&GT; 这两个都没有了。
  • 的IsReadOnly - 问答LT; T&GT; 堆栈&LT; T&GT; 容易的可以的都没有了。
  • 添加 - 问答LT; T&GT; 可以明确地实现这个(与入队),则有可能堆栈&LT; T&GT; (用
  • 清除 - 检查
  • 包含 - 检查
  • CopyTo从 - 检查
  • 的GetEnumerator - 检查(杜)
  • 删除 - 这是唯一一个问答LT; T&GT; 堆栈&LT; T&GT; 没有一个完美匹配
  • Count -- Queue<T> and Stack<T> both have this.
  • IsReadOnly -- Queue<T> and Stack<T> easily could have this.
  • Add -- Queue<T> could implement this explicitly (with Enqueue), as could Stack<T> (with Push).
  • Clear -- Check.
  • Contains -- Check.
  • CopyTo -- Check.
  • GetEnumerator -- Check (duh).
  • Remove -- This is the only one that Queue<T> and Stack<T> don't have a perfect match for.

和这里是真正的踢球者:的ICollection&LT; T&GT;卸下摆臂返回布尔 ;这样明确的实施问答LT; T&GT; 可以完全(例如)检查是否要删除的产品的实际上的头元素(使用皮克),如果是的话,调用出列并返回 ,否则返回堆栈&LT; T&GT; 可以很容易地得到一个类似的实现与皮克流行

And here's the real kicker: ICollection<T>.Remove returns a bool; so an explicit implementation for Queue<T> could totally (for example) check if the item to be removed is actually the head element (using Peek), and if so, call Dequeue and return true, otherwise return false. Stack<T> could easily be given a similar implementation with Peek and Pop.

好了,现在我已经写了一万字,为什么的 I 的认为这将是可能的,我提出了一个明显的问题:为什么的没有 队列&LT; T&GT; 和堆栈&LT; T&GT; 实现这个接口这是什么是设计因素(这我可能不会考虑)导致的决定,这将是个错误的选择?为什么的ICollection 实施呢?

All right, now that I've written about a thousand words on why I think this would be possible, I pose the obvious question: why didn't the designers of Queue<T> and Stack<T> implement this interface? That is, what were the design factors (which I am probably not considering) that led to the decision that this would be the wrong choice? Why was ICollection implemented instead?

我如果想知道,在设计我的的类型,有什么我就考虑到接口的实现,我可能会俯瞰问这个问题的指导原则。例如,被它只是认为不好的做法,明确落实未完全,一般支持的接口(如果是这样,这似乎有,例如,名单,其中有冲突; T&GT; 实施的IList )?是否有一个队列/栈的概念,什么之间的概念的断开的ICollection&LT; T&GT; 是为了重新present

I am wondering if, in designing my own types, there are any guiding principles I should consider with respect to interface implementation that I might be overlooking in asking this question. For example, is it just considered bad practice to explicitly implement interfaces that aren't fully supported in general (if so, this would seem to conflict with, e.g., List<T> implementing IList)? Is there a conceptual disconnect between the concept of a queue/stack and what ICollection<T> is meant to represent?

基本上,我感觉到,必须有一个pretty的很好的理由问答LT; T&GT; (例如)的的实施的ICollection&LT; T&GT; ,我不想只是去一味的向前设计我自己的类型和实施以不当方式的接口,无需被告知并完全通过了我的思维]丢。

Basically, I sense that there must be a pretty good reason Queue<T> (for example) doesn't implement ICollection<T>, and I don't want to just go blindly forward designing my own types and implementing interfaces in an inappropriate manner without being informed and fully thinking through what I'm doing.

我不道歉,超长的问题。

I do apologize for the super-long question.

推荐答案

我不能给什么是思想实际的答案 - 也许是设计师的人会给我们的真正的thinkng我可以删除。

I can't give the "what was the actual thinking" answer - perhaps one of the designers will give us the real thinkng and I can delete this.

不过,把自己的心态如果有人来找我做出这个决定,我能想到的答案..让我说明这个code:

However, putting myself in the mindset of "what if someone came to me to make this decision", I can think of an answer.. let me illustrate with this code:

public void SomeMethod<T>( ICollection<T> collection, T valueA, T valueB)
{

  collection.Add( valueA);
  collection.Add( valueB);

  if( someComplicatedCondition())
  {
    collection.Remove(valueA);
  }
}

(当然,任何人都可以创建一个坏的实施的ICollection&LT的; T&GT; ,但我们预计该框架设置的例子)。让我们假设堆栈/队列实施,因为你在问题中的状态。所以是code以上的权利,还是有优势的情况下的错误,因为的ICollection&LT; T&GT;卸下摆臂()应检查?如果值a 必须被删除,如何解决这与两个协议栈的的队列工作?有答案,但显然code以上是错误在这种情况下 - 尽管它的气味合理

(Sure, anyone can create a bad implementation of ICollection<T>, but we expect the framework to set the example). Let's assume Stack/Queue implement as you state in the question. So is the code above right, or does it have edge case bugs because ICollection<T>.Remove() should be checked? If valueA MUST be removed, how do I fix this to work with both Stack and Queue? There are answers, but obviously the code above is wrong in this case - even though it smells reasonable.

所以,这两个跨pretations是有效的,但我很好在这里做出的决定 - 如果我有code以上,知道我可以通过一个队列或堆栈,我可以设计它周围,但它肯定会是一个简单的错误坑掉进(到处都可以看到的ICollection&LT; T&GT;!,记得删除边缘的情况下)

So both interpretations are valid, but I'm good with the decision made here - if I had the code above and knew I could be passed a Queue or Stack that I could design around it, but it sure would be an easy bug pit to fall into (everywhere you see ICollection<T>, remember the edge cases for remove!)

这篇关于为什么队列(T)和堆栈(T)未实现的ICollection(T)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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