0

Here is the problem: I'm trying to trigger an event in a curtain method of a class. For instance I got a class named clMage that inherits from clUnits and it got public method attMagicMissle(clUnit aU). Well here is the code for the clUnits declaration:

    public class clUnits
    {
        public int iHitPoints { get; set; }
        public int iDamage { get; set; }
        public ArmorType unitArmor { get; set; }
    }

And here is the clMage with it's troublesome method:

    public class clMage : clUnits
    {
        public event evtDamageDone damageDealtToSoldier;
        public event evtDamageDone damageDealtToArcher;
        public event evtDamageDone damageDealtToMage;

        public clUnits currentTarget { get; set; }

        public AttackType mageAttack { get; set; }
        public clMage(int iHP, int iDamage, AttackType atType, ArmorType arType)
        {
            this.iHitPoints = iHP;
            this.iDamage = iDamage;
            this.mageAttack = atType;
            this.unitArmor = arType;
        }

        public int attMagicMissle(clUnits aU)
        {
            int iDamageDeals = 0;
            currentTarget = aU;

            switch (currentTarget.unitArmor)
            {
                case ArmorType.None:
                    {
                        iDamageDeals = iDamage * 2;
                    }


          break;
            case ArmorType.Heavy:
                {
                    iDamageDeals = Convert.ToInt32(iDamage * 1.5);
                    this.damageDealtToSoldier(currentTarget); // Here is the NullReferenceExeption problem starts
                }
                break;
            case ArmorType.Medium:
                {
                    iDamageDeals = Convert.ToInt32(iDamage * 0.5);
                    this.damageDealtToArcher(currentTarget);
                } break;
            case ArmorType.Light: 
                { 
                    iDamageDeals = iDamage;
                    this.damageDealtToMage(currentTarget);
                } break;
        }

        return iDamageDeals;
    }
}

And here goes the Main():

    public delegate int Attack(clUnits aUnit);
    public delegate void evtDamageDone(object aUnit);
    public enum AttackType { None, Melee, Range, Mage }
    public enum ArmorType { None, Heavy, Medium, Light}
    class Program
    {
        static void Main(string[] args)
        {
            Attack Strikes;
            clWarrior theSoldier = new clWarrior(750, 75, AttackType.Melee, ArmorType.Heavy);
            clArcher theArcher = new clArcher(500, 100, AttackType.Range, ArmorType.Medium);
            clMage theMage = new clMage(250, 150, AttackType.Mage, ArmorType.Light);

            // Mage actions
            Console.WriteLine("The mage: ");
            Strikes = theMage.attMagicMissle;
            Console.WriteLine("Attack hase damage = {0} attacks the soldier for {1} damage!", theMage.iDamage, Strikes(theSoldier));
            Console.WriteLine("Attack hase damage = {0} attacks the archer for {1} damage!", theMage.iDamage, Strikes(theArcher));
            Console.WriteLine("Attack hase damage = {0} attacks the mage for {1} damage!", theMage.iDamage, Strikes(theMage));

            // Archer actions
            Console.WriteLine("The archer: ");
            Strikes = theArcher.attArrowShot;
            Console.WriteLine("Attack hase damage = {0} attacks the soldier for {1} damage!", theArcher.iDamage, Strikes(theSoldier));
            Console.WriteLine("Attack hase damage = {0} attacks the archer for {1} damage!", theArcher.iDamage, Strikes(theArcher));

            Console.WriteLine("Attack hase damage = {0} attacks the mage for {1} damage!", theArcher.iDamage, Strikes(theMage));

            // Soldier actions
            Console.WriteLine("The soldier: ");
            Strikes = theSoldier.attSwordSlash;
            Console.WriteLine("Attack hase damage = {0} attacks the soldier for {1} damage!", theSoldier.iDamage, Strikes(theSoldier));
            Console.WriteLine("Attack hase damage = {0} attacks the archer for {1} damage!", theSoldier.iDamage, Strikes(theArcher));
            Console.WriteLine("Attack hase damage = {0} attacks the mage for {1} damage!", theSoldier.iDamage, Strikes(theMage));
        }
    }

Well yeah... I'm sitting with it for quite some time already(9 hours) surfing the web and stackoverflow mainly, but I just can't get why on the commented line for the clMage it gives me that error and therefore can't understand how to fix it!

Cœur
  • 37,241
  • 25
  • 195
  • 267

1 Answers1

1

If no one subscribed to it, then damageDealtToSoldier is null, so invoking it causes a NullReferenceException. You need to check whether it's null:

if (this.damageDealtToSoldier != null)
    this.damageDealtToSoldier(currentTarget);

Typically, people create a method like this to raise the event:

protected virtual void OnDamageDealtToSoldier(object aUnit)
{
    var handler = this.damageDealtToSoldier;
    if (handler != null)
        handler(aUnit);
}
Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
  • At some I've point lost the importance of the listening thing for event, - the source I used to learn the events didn't point it out that if a "listener" doesn't exist then the handler is going to return null. In addition to this another thing that I think must be pointed out is that: a listener must be declared before the lines that are triggering the event otherwise the handlers are to return null. Hope this topic I rised is going to be helpful to other lost in the "labyrinths of events". And big thanks to Thomas Levesque for giving me the leading point for solving my problem. – Ryu Akira Kenshin Yuki May 13 '14 at 00:57