maxilaxen
maxilaxen

Reputation: 55

I cant reach a method (Images)

I'm creating a game in order to learn C# programming.

I have a class called Unit and two derived types, Wolf and Spider.

I've also created a class called UnitList that contains a List<Unit> where I would like to store my Unit instances.

There is also another class called Battle where a method loops through each Unit in my List<Unit>. I would like to use a different method based on the Type of Unit, be it a Wolf or a Spider.

Please see the image below as I am not good at explaining concepts; I have been stuck on this for days.

Image

Upvotes: 0

Views: 70

Answers (2)

Bradford Dillon
Bradford Dillon

Reputation: 1800

What you are probably looking for is the c# is operator.

For example

if(unit is Wolf)
{
    // Do something
}
else if (unit is Spider)
{
    // Do Something
}

C# is operator on MSDN

Once you are in those blocks, you can use a type cast to call your methods.

if(unit is Wolf)
{
    ((Wolf)unit).WolfAttack();
}

However, there is a much cleaner way of doing this in C# using the inheritance tree you have already set up.

class Unit
{
    public virtual void Attack()
    {
        Console.WriteLine("Unit attacks!");
    }
}

class Wolf : Unit
{
    public override void Attack()
    {
        Console.WriteLine("Wolf attacks!");
    }
}

class Spider : Unit
{
    public override void Attack()
    {
        Console.WriteLine("Spider attacks!");
    }
}

By marking the method on Unit as virtual you can override its behavior on classes that inherit from Unit. Thus your code to call the attack now just becomes

foreach(Unit unit in team1.GetList())
{
    unit.Attack();
}

as it will call the proper Attack() function for each Unit be it a Spider or a Wolf.

There is also an alternative to this, and that is to use Interfaces. If there is no shared implementation between the Spider and Wolf class, this is often a good way to go rather than using abstract classes.

You would define an IUnit interface, for example

public IUnit
{
    int Health { get; set; }
    void Attack();
}

Then instead of inheriting from Unit you would implement IUnit instead.

class Wolf : IUnit
{
    public int Health { get; set; }

    public void Attack()
    {
        Console.WriteLine("Wolf attacks!");
    }
}

class Spider : IUnit
{
    public int Health { get; set; }

    public void Attack()
    {
        Console.WriteLine("Spider attacks!");
    }
}

You would then use IUnit in place of Unit.

Both methods are valid, and both have advantages and disadvantages. Classes are allowed to implement many interfaces, but only inherit one class. Interfaces can not define functionality, so they can't completely replace inheritance. There are more, but that is the most basic difference between the two.

Upvotes: 1

user1598725
user1598725

Reputation: 60

You're trying to compare a System.Type with an instance. What you're looking to do is use the typeof operator or the is/as construct for C#. Rather, for a better solution, you could use inheritance.

You're Unit class could be declared abstract as such:

abstract class Unit
{
    private int health;
    private int damage;

    protected Unit()
    {
        health = 100;
    }

    public abstract void Attack();
}

While your Wolf class could be:

class Wolf : Unit
{
    public override void Attack()
    {
        // Do Something...
    }
}

And you could then retrieve each Unit instance from your list and call Unit.Attack(); and it would call the respective Attack().

Upvotes: 1

Related Questions