在ICollection<T>上使用ElementAt(index)

3
作为提醒,我目前正在学习C#,并在阅读一本教科书时遇到了这个障碍。
如何从IEnumerable<T>中调用 ElementAt? SO 问题中的第二条评论提到了它,但我只得到了一个错误。 这里 他们也提到了这样做,但他们没有告诉你如何
如果我遗漏了一些基本内容,请看看我的代码:
using System.Collections.Generic;

class Card {}

class Deck
{
    public ICollection<Card> Cards { get; private set; }

    public Card this[int index]
    {
        get { return Cards.ElementAt(index); }
    }
}

我从 MSDN Library page 获取的信息得出了这个结论:
class Deck
{
    public ICollection<Card> Cards { get; private set; }

    public Card this[int index]
    {
        get {
        return System.Linq.Enumerable.ElementAt<Card>(Cards, index); 
        }
    }
}

所有这些都来自于关于集合的部分,第二段代码实现使得从列表中获取特定元素比必须遍历枚举器更加容易。
Deck deck = new Deck();
Card card = deck[0];

而不是:

Deck deck = new Deck();
Card c1 = null;
foreach (Card card in deck.Cards){
    if (condition for the index)
         c1 = card;
}

我是否做对了,或者我漏掉了什么?感谢任何意见!


你得到了什么错误? - Matt Ellen
你不能直接跳到一个元素并获取它,因为内部机制总是使用一些 Enumerator。当然,当你调用 ToList 或类似的方法时,实际上会迭代一次。 - King King
我收到的错误是它找不到定义。 - qdev76
1
@KingKing 当然,如果Cards实际上是一个IListElementAt将会使用它的索引器。 - p.s.w.g
@p.s.w.g 看起来 OP 的卡牌是 ICollection,如果它也实现了 IList,那就没问题。 - King King
你们两个都是对的,但我是在学习如何从ICollection调用索引器。感谢你们的建议。 - qdev76
3个回答

9

如果您想使用Linq扩展方法,请确保在文件顶部包含System.Linq命名空间:

using System.Collections.Generic;
using System.Linq; // This line is required to use Linq extension methods

class Card {}

class Deck
{
    public ICollection<Card> Cards { get; private set; }

    public Card this[int index]
    {
        get { return Cards.ElementAt(index); }
    }
}

当然,扩展方法只是带有一点语法糖的普通方法。您也可以这样调用它们:
using System.Collections.Generic;

class Card {}

class Deck
{
    public ICollection<Card> Cards { get; private set; }

    public Card this[int index]
    {
        get { return System.Linq.Enumerable.ElementAt(Cards, index); }
    }
}

1

这被称为扩展方法。

确保你已经引用了System.Linq

然后只需要执行Cards.ElementAt(index)

也许你想使用具有索引器的IList<T>


谢谢,我以为我知道扩展方法是如何工作的,但我想我需要更详细地了解它。 - qdev76

0

“简单”的答案是,您应该将“Deck”声明为:IList(或Array…基本上对于此讨论来说是相同的)。

“更长”的答案在于“ICollection”的混淆……ICollection要么是 (1)具有已知计数但没有已知(或保证)顺序的IEnumerable。 (想象一下一个数据存储器,它知道计数,但直到您读取数据才固定顺序。) -或- (2)一个抽象,其中您知道计数并且具有已知或可靠的顺序,但自然没有随机访问……例如:堆栈或队列。

区别在于#2使用IndexAt(int n)是O(1)(非常快),但#1不是O(1),而是O(n)(较慢)。

因此,我的结论是,如果您想要随机访问,请选择支持它的数据结构(IList或Array,但不是ICollection)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接