【问题标题】:C# Custom Event is NULL [duplicate]C#自定义事件为NULL [重复]
【发布时间】:2018-10-01 12:19:45
【问题描述】:

我在这里遇到了事件问题,

在你写“重复”之前,我会说我已经完成了它并且我不太擅长编程,这就是我问的原因。

问题是我的事件没有触发

调试器说:=>“OnCollision 为 Null”

编辑:调试器部分

OnCollision 是我的事件

感谢您的帮助:D

那是我的 EventArgs

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

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

点击控制

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()
    { }
}

方法

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

    }

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);

【问题讨论】:

  • 您在 IsHit 属性中触发事件,但您从未在属性的 set 部分设置 isHit 支持字段。
  • @Guardian,你有 isHit 变量和一个名为 IsHit 的属性。通常, isHit 将是私有的,因此无法在类外部访问它,然后任何针对该类进行编程的人都将使用公共 IsHit 属性来设置值。在属性的 set 部分中,您将调用 isHit = value; 但您从不调用它,因此 isHit 永远不会从初始值更改。

标签: c# winforms events


【解决方案1】:

问题在于IsHit 属性是在事件连接之前设置的。要安全地触发事件,请使用以下语法而不是直接调用:

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

?.(所谓的 Elvis)运算符首先检查 OnCollision 是否不是 null,并且仅在这种情况下调用 Invoke 方法,该方法实际上执行事件。直接使用OnCollision(sender, new CollisionEventArgs(true))是不行的,因为没有事件订阅者时,OnCollision就是null,会抛出NullReferenceException

如果您使用的是不支持 ?. 运算符的早期版本的 C#,您可以改为执行以下操作:

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

正如我演示的那样,将当前实例存储在单独的变量中比直接使用OnCollision 更安全,因为它可能会在多线程环境中导致问题。有关更多信息,请参阅this 答案。幸运的是 ?. 不会发生这种情况,因为它已经以线程安全的方式构建,并且基本上在后台执行相同的操作。

【讨论】:

  • 我已经更新了答案
  • sender 在这种情况下应该是this,我已经在答案中替换了它。代码应该代替IsHit setter 中的OnCollision(this, new CollisionEventArgs(true)); 行。
  • 在哪一行?您应该在调试器中运行它并查看它何时实际抛出
  • 图片中null是哪个变量?
  • @Guardian,public delegate void CollisionHandler(object current, CollisionEventArgs cea); 行是在您使用它的类之外定义的吗?回顾我在 VS2005 中声明委托时的旧代码,它们总是在类中定义。
猜你喜欢
  • 2012-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多