qdev76
qdev76

Reputation: 149

ElementAt(index) on ICollection<T>

As a heads up, I'm learning C# at the moment and going through a textbook when I ran into this obstacle.

How do you call ElementAt from an IEnumerable<T>? The second comment in this SO question mentions it, but I just get an error.

Here they mention doing it as well, but they don't tell you how!

In case I'm missing something basic, here's my code:

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

I've resorted to this from the information I got on the 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); 
        }
    }
}

All this comes from the section on collections and how the second code implementation I showed makes it easier to grab a specific element from the list rather than having to iterate through the enumerator.

Deck deck = new Deck();
Card card = deck[0];

Instead of:

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

Am I doing this right or am I missing something? Thanks for any input!

Upvotes: 3

Views: 6181

Answers (3)

John Wardale
John Wardale

Reputation: 131

The "simple" answer is that you should declare "Deck" as: IList (or Array ... basically the same for this discussion.)

The "Longer" answer lies in the confusion of "What is ICollection" ... ICollection is either (1) an IEnumerable with a known Count but NO known (or guaranteed) order. (Imagine a data-store that knows the count but doesn't fix the order until you read the data.) -or- (2) an abstraction where you KNOW the count and have a known or dependable order, but do NOT naturally have random-access ... eg: a stack or a queue.

The minor difference is using IndexAt(int n) for #2 is O(1) (very fast), but O(n) (slower) NOT O(1) for #1 .

So, my conclusion is if you want random access, then pick data structure that you KNOW supports is (IList or Array, but not ICollection).

Upvotes: 0

Daniel A. White
Daniel A. White

Reputation: 190935

It is called an extension method.

Ensure you have System.Linq referenced.

Then just do Cards.ElementAt(index)

Perhaps you would like to use a IList<T> which has an indexer.

Upvotes: 1

p.s.w.g
p.s.w.g

Reputation: 149020

If you want to use Linq extension methods, make sure you include the System.Linq namespace at the top of your file:

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

Of course, extension methods are just regular old methods with a little bit of syntactic sugar. You could also call them this way:

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

Upvotes: 9

Related Questions