3

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!

Community
  • 1
  • 1
qdev76
  • 149
  • 1
  • 9
  • What is the error that you get? – Matt Ellen Nov 16 '13 at 00:38
  • you can't, the internal mechanism always uses some `Enumerator` and you can't jump right to an element and fetch it. Of course when you call `ToList` or some similar method, you actually iterate it once – King King Nov 16 '13 at 00:38
  • the error i'm getting is that it can't find the definition – qdev76 Nov 16 '13 at 00:39
  • 1
    @KingKing Of course if `Cards` is actually an `IList`, `ElementAt` will use it's indexer anyway. – p.s.w.g Nov 16 '13 at 00:43
  • @p.s.w.g looks like the OP's cards is icollection, if it also implements IList, it's OK. – King King Nov 16 '13 at 00:50
  • you guys are both right, but I was looking at how to call the indexer from ICollection for learning purposes. Thanks for the input – qdev76 Nov 16 '13 at 02:25

3 Answers3

9

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); }
    }
}
p.s.w.g
  • 146,324
  • 30
  • 291
  • 331
1

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.

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
  • thanks, I thought I knew how extension methods work, but I guess I have to look into it in more detail – qdev76 Nov 16 '13 at 00:44
0

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).

John Wardale
  • 121
  • 1
  • 3