IEnumerable 和 IEnumerable之间的区别?

发布于 2024-10-17 04:15:29 字数 776 浏览 1 评论 0原文

IEnumerableIEnumerable 之间有什么区别?

我见过许多框架类都实现了这两个接口,因此我想知道通过实现这两个接口可以获得什么优势?

请看一下它们是如何定义的:

public interface IEnumerable
{
    [DispId(-4)]
    IEnumerator GetEnumerator();
}
public interface IEnumerable<T> : IEnumerable
{
    IEnumerator<T> GetEnumerator();
}

正如我们所见,IEnumerable 派生自 IEnumerable,这意味着无论 IEnumerable 具有什么, IEnumerable 继承了,那么为什么我们要实现两者而不是仅仅实现 IEnumerable 呢?实现 IEnumerable 还不够吗?

同样,还有其他类似的对:

  • IListIList
  • ICollectionICollection

我会也想了解这些。

What is the difference between IEnumerable and IEnumerable<T>?

I've seen many framework classes implementing both these interfaces, therefore I would like to know what advantages one get by implementing both?

Please have a look how they've been defined:

public interface IEnumerable
{
    [DispId(-4)]
    IEnumerator GetEnumerator();
}
public interface IEnumerable<T> : IEnumerable
{
    IEnumerator<T> GetEnumerator();
}

As we see, IEnumerable<T> derives from IEnumerable, that means whatever IEnumerable has, IEnumerable<T> inherits, then why do we implement both instead of just IEnumerable<T>? Is implementing IEnumerable<T> not enough?

Likewise, there are other similar pairs:

  • IList and IList<T>
  • ICollection and ICollection<T>

I would like to know about these as well.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

居里长安 2024-10-24 04:15:29

基本上,在 .NET 1.0 和 1.1 中,非泛型接口首先出现。然后,当 .NET 2.0 出现时,通用的等效项也出现了。如果泛型已经进入 .NET 1.0,生活会简单得多:)

就“仅”实现 IEnumerable 而不是两者实现而言 - 您基本上拥有要实现这两者,并且您还必须使用显式接口实现,因为两者都定义了无参数 GetEnumerator 方法。由于 IEnumerator 也扩展了 IEnumerator,它通常是这样的:

public IEnumerator<T> GetEnumerator()
{
    // Return real iterator
}

// Explicit implementation of nongeneric interface
IEnumerator IEnumerable.GetEnumerator()
{
    // Delegate to the generic implementation
    return GetEnumerator();
}

另一方面,随着 C# 2 中引入的迭代器块(使用 yield return< /code> 等)幸运的是,您很少需要完全手动实现这些事情。您可能需要编写类似上面的内容,然后在 GetEnumerator 方法中使用 yield return

请注意,IList扩展 IList,而 ICollection不< /em> 扩展ICollection。这是因为这样做的类型安全性较差...而任何泛型迭代器都可以被视为非泛型迭代器,因为任何值都可以(可能装箱)转换为 objectIList< /code> 和 ICollection 允许将值添加到集合中;并且向 IList 添加(比如说)字符串是没有意义的。

编辑:我们需要 IEnumerable的原因是我们可以以类型安全的方式进行迭代,并传播该信息。如果我向您返回一个 IEnumerable,您就知道您可以放心地假设从它返回的所有内容都将是字符串引用或 null。使用 IEnumerable,我们必须有效地转换(通常在 foreach 语句中隐式地)从序列返回的每个元素,因为 Current 属性IEnumerator 的类型只是 object。至于为什么我们仍然需要IEnumerable - 因为基本上旧的接口永远不会消失。有太多现有代码使用它。

IEnumerable 可以不扩展 IEnumerable,但任何想要使用 IEnumerable 的代码无法调用接受 IEnumerable 的方法 - 并且 .NET 1.1 和 1.0 中有很多类似的方法。

Basically the nongeneric interfaces came first, in .NET 1.0 and 1.1. Then when .NET 2.0 came out, the generic equivalents came out. Life would have been a lot simpler if generics had made it into .NET 1.0 :)

In terms of implementing "only" IEnumerable<T> instead of both - you basically have to implement both, and you have to use explicit interface implementation too, given that both define a parameterless GetEnumerator method. As IEnumerator<T> extends IEnumerator too, it's normally something like this:

public IEnumerator<T> GetEnumerator()
{
    // Return real iterator
}

// Explicit implementation of nongeneric interface
IEnumerator IEnumerable.GetEnumerator()
{
    // Delegate to the generic implementation
    return GetEnumerator();
}

On the other hand, with the iterator blocks introduced in C# 2 (with yield return etc) you rarely need to implement these things entirely by hand, fortunately. You may need to write something like the above, and then use yield return in the GetEnumerator method.

Note that IList<T> does not extend IList, and ICollection<T> does not extend ICollection. That's because it's less type-safe to do so... whereas any generic iterator can be seen as a nongeneric iterator due to the (potentially boxing) conversion of any value to object, IList and ICollection allow values to be added to the collection; and it doesn't make sense to add (say) a string to an IList<int>.

EDIT: The reason why we need IEnumerable<T> is so that we can iterate in a type-safe way, and propagate that information around. If I return an IEnumerable<string> to you, you know that you can safely assume everything returned from it will be a string reference or null. With IEnumerable, we had to effectively cast (often implicitly in a foreach statement) each element that was returned from the sequence, because the Current property of IEnumerator is just of type object. As for why we still need IEnumerable - because old interfaces never go away, basically. There's too much existing code using it.

It would have been possible for IEnumerable<T> not to extend IEnumerable, but then any code wanting to make use of an IEnumerable<T> couldn't call into a method accepting IEnumerable - and there were a lot of methods like that from .NET 1.1 and 1.0.

听不够的曲调 2024-10-24 04:15:29

一个返回 Object 类型的对象,另一个返回 T 类型的对象。

One returns an object of type Object, the other returns an object of type T.

李不 2024-10-24 04:15:29

至于为什么你会看到定义这两者的类,尽管 IEnumerable< 已经足够了。 T>实现 IEnumerable,它不是必需的,但在自我文档中有时可以列出子接口,这是很好的。考虑

interface IA { }
interface IB : IA { }

class A : IB {} // legal, IB implements IA

class B : IA, IB {} // also legal, possible more clear on intent

As to why you see classes defining both, enough though IEnumerable< T > implements IEnumerable, its not needed but is is nice in a self documenting to list the sub interfaces at times. Consider

interface IA { }
interface IB : IA { }

class A : IB {} // legal, IB implements IA

class B : IA, IB {} // also legal, possible more clear on intent
那请放手 2024-10-24 04:15:29

在循环迭代时,IEnumerator 会维护状态。
它会记住光标位置,而 IEnumerable 不会。

While iterating through the loop IEnumerator maintains the state.
It remembers the cursor position and IEnumerable does not.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文