I’m working on a library to use in a card game. I spent a couple of hours learning indexers so I could have a Deck class that functions like an array of Card types. Then I achieved the same thing and a whole lot more by inheriting from ArrayList. I therefore ask why one would go to the trouble of making a class indexable when the same thing (and much more) can be achieved via “: ArrayList”.
I think my question is pretty self explanatory, but for those who like to look at code.
Here is my Deck class that contains an indexer:
class DeckIndexer
{
private Card[] myData;
private int arrSize;
public DeckIndexer(int size)
{
arrSize = size;
myData = new Card[size];
for (int i = 0; i < size; i++)
{
myData[i] = null;
}
}
public Card this[int pos]
{
get
{
return myData[pos];
}
set
{
myData[pos] = value;
}
}
public Card this[Card c]
{
get
{
int count = 0;
for (int i = 0; i < arrSize; i++)
{
if (myData[i] == c)
{
count++;
}
}
return c;
}
set
{
for (int i = 0; i < arrSize; i++)
{
if (myData[i] == c)
{
myData[i] = value;
}
}
}
}
}
Now here is the second solution, inheriting from ArrayList
class DeckInheritence : ArrayList
{
}
The second solution gives me 20+ methods for free, [] syntax, and saves me however many lines of code. The first gives me [] syntax, the methods attached to object, and is hard to implement.
BTW, yes I can see that ArrayList is giving me an array of objects, not cards, but there is not much fudging to get it to require a Card type.
Firstly, unless you are in .NET 1.1,
List<Card>would be preferable. However, as for inheriting… if all you are doing is representing a list of cards, I would just useList<Card>(with neither encapsulation nor inheritance).As for the why; encapsulation is useful when being a list is not the primary purpose of a type, but it is useful for the caller to have access to a few methods like indexers. As Jon notes, inheriting doesn’t (for example) give you any control over what the user does to your data.
Personally, I don’t recommend inheriting from
List<T>(orArrayList); that binds an implementation detail into the actual type declaration (changing inheritance is a breaking change).If you want to expose lots of methods with minimal work, all you need to do is provide
IEnumerable<T>(as an interface) – then all of LINQ becomes available. So if you need something bespoke (more thanList<Card>) my advice would be:List<T>(i.e. a private field)IEnumerable<T>if appropriate (just returntheList.GetEnumerator())