0

i got a Problem here with Events,

before your write "duplicate", im going to say that i ve done it alrdy and im not that good at programming thats why am i asking yet.

Problem is that my Event doesnt fire

debugger says :=> "OnCollision is Null"

EDIT: DEBUGGER PART

enter image description here

OnCollision is my Event

thanks for help :D

Thats my EventArgs

public class CollisionEventArgs : EventArgs
{
    public bool Hit { get { return hit; } }
    private bool hit;

    public CollisionEventArgs(bool _hit)
    {
        this.hit = _hit;
    }
}

HitControl

public delegate void CollisionHandler(object current, CollisionEventArgs cea);
public class HitControl : Button
{
    public event CollisionHandler OnCollision;
    public bool IsHit
    {
        get { return isHit; }
        set
        {
            if (OnCollision != null)
            {
                if (this.Width > 100)
                OnCollision(this, new CollisionEventArgs(true));
            }
        }
    }
    public bool isHit;

    public HitControl()
    { }
}

Method

 private void hitControl1_OnCollision_1(object current, CollisionEventArgs cea)
    {
        MessageBox.Show("a");

    }

Code in Designer [Sub]

// 
        // hitControl1
        // 
        this.hitControl1.IsHit = false;
        this.hitControl1.Location = new System.Drawing.Point(115, 183);
        this.hitControl1.Name = "hitControl1";
        this.hitControl1.Size = new System.Drawing.Size(175, 23);
        this.hitControl1.TabIndex = 1;
        this.hitControl1.Text = "hitControl1";
        this.hitControl1.UseVisualStyleBackColor = true;
        this.hitControl1.OnCollision += new CollisionHandler(this.hitControl1_OnCollision_1);
  • You fire the event in the IsHit property but you never set the isHit backing field in the set part of the property. – Handbag Crab Oct 01 '18 at 12:27
  • @Guardian, you have the isHit variable and a property called IsHit. Normally, isHit would be private so it's not accessible outside the class, then anyone programming against the class would use the public IsHit property to set the value. In the set part of the property you would call `isHit = value;` but you never call this so isHit never changes from the initial value. – Handbag Crab Oct 01 '18 at 12:36

1 Answers1

2

The problem is that the IsHit property is set before the event is wired up. to safely fire events use the following syntax instead of calling directly:

OnCollision?.Invoke(this, new CollisionEventArgs(true));

The ?. (so-called Elvis) operator first checks if the OnCollision is not null and only in that case calls the Invoke method, which essentially executes the event. Using OnCollision(sender, new CollisionEventArgs(true)) directly doesn't work, because when there is no subscriber of the event, OnCollision is null and NullReferenceException is thrown.

In case you are using an earlier version of C# that doesn't support ?. operator, you can do the following instead:

var handler = OnCollision;
if ( handler != null )
{
   handler(this, new CollisionEventArgs(true));
}

It is safer to store the current instance in separate variable as I demonstrated instead of using OnCollision directly, because it could cause problems in multi-threaded environments. See this answer for more info. Luckily for ?. this does not happen, as that is already built in a thread safe manner and essentially does the same thing in the background.

Martin Zikmund
  • 38,440
  • 7
  • 70
  • 91
  • 1
    I have updated my answer – Martin Zikmund Oct 01 '18 at 12:33
  • 1
    `sender` should be `this` in this case, I have replaced it in the answer. The code should go instead of the `OnCollision(this, new CollisionEventArgs(true));` line in `IsHit` setter. – Martin Zikmund Oct 01 '18 at 12:41
  • 1
    On which line? You should run this in debugger and see when it actually throws – Martin Zikmund Oct 01 '18 at 12:50
  • 1
    Which variable is `null` in the image? – Martin Zikmund Oct 01 '18 at 12:55
  • 1
    @Guardian, could it be that the line `public delegate void CollisionHandler(object current, CollisionEventArgs cea);` is defined outside of the class that you're using it in? Looking back at my old code from VS2005 when I've declared delegates they're always defined within the class. – Handbag Crab Oct 01 '18 at 13:00
  • @HandbagCrab , handler still be null :/ –  Oct 01 '18 at 13:03
  • But that should be OK, as we check `handler != null` – Martin Zikmund Oct 01 '18 at 13:07
  • @Guardian, Probably time to go back to basics. Create a simple class that fires an event and another simple class that handles it. Then run the code to fire the event. If that fails, add the code to your question so that we can download it and try it ourselves. Your current code has more going on that we can't see so is difficult to diagnose. – Handbag Crab Oct 01 '18 at 13:15