Reputation: 424
I am still learning the ins and outs of C#, from a Python background.
With that in mind, let's say I am making a game. For simplicity's sake, let's base it on Magic: the Gathering or any other popular collectible card game. In such a game, there are multiple cards that can be played. These cards would have different types and effects. for example, there can be a creature card, and there might be a spell card.
These types of cards have different attributes. A creature would, for example, have an attack
attribute and a health
attribute, while a spell might have an effect
attribute. However, these different types would still be cards, and have multiple things in common, like a cost
attribute. These different cards might be managed by a Manager
class. A basic code sample from such a game might look like this:
public class Manager
{
public CreatureCard card1 = new CreatureCard();
public SpellCard card2 = new SpellCard();
}
public class Card
{
public int cost;
}
public class CreatureCard : Card
{
public int attack;
public int health;
}
public class SpellCard : Card
{
public SpellEffect effect;
}
What I basically want to do, is create cards and store them in the manager class without knowing whether they're a spell or a creature in advance. The manager class might then look like this:
public class Manager
{
public Card card1;
public Card card2;
}
The cards would be assigned from somewhere else.
Now, this doesn't really work. There would be no way of accessing a card's health
attribute, for example. This is pretty logical, as the card might not even have a health
attribute.
This is why I am looking for an approach that does work, while keeping the structure about the same. So there would be a Card
class, that has lotsa stuff in it, and other classes derived from it (CreatureCard
, SpellCard
).
Is there a way to make this work? I am coming from Python here, so this approach might actually be totally wrong in C#. If so, please tell me what kind of approach I could use instead of the one I'm trying to get to work right now.
Upvotes: 3
Views: 3287
Reputation: 149020
You can do it by casting the Card
instance appropriately:
public class Manager
{
public Card card1;
public Card card2;
}
...
var manager = new Manager
{
card1 = new CreatureCard();
card2 = new SpellCard();
}
if (manager.card1 is CreatureCard)
{
var health = ((CreatureCard)manager.card1).Health;
Console.WriteLine(health);
}
if (manager.card2 is SpellCard)
{
var effect = ((SpellCard)manager.card2).effect;
Console.WriteLine(effect);
}
Or like this:
var creatureCard = manager.card1 as CreatureCard;
var spellCard = manager.card2 as SpellCard;
if (creatureCard != null)
{
Console.WriteLine(creatureCard.health);
}
if (spellCard != null)
{
Console.WriteLine(spellCard.effect);
}
To expand on this:
To test if a card is of a specified type, use the is
operator:
bool isCardType = myCard is CardType;
Use (CardType)
to cast / convert the card to the specified type:
CardType specificCardType = (CardType)myCard;
To safely cast a card to a specific type or return null if it's not of that type, use the as
operator:
CardType specificCardType = myCard as CardType;
if (specificCardType != null) {
...
}
Upvotes: 4