简单事件c#

简单事件c#,c#,events,exception,C#,Events,Exception,我有两个类,我必须制作一个事件来在这些类之间进行通信 Class a { public delegate void delegat(int a); public event delegat exit; ... private void a_FormClosed(object sender, FormClosedEventArgs e) { // My event named exit should run here, but I get

我有两个类,我必须制作一个事件来在这些类之间进行通信

Class a
{
    public delegate void delegat(int a);
    public event delegat exit;
    ...
    private void a_FormClosed(object sender, FormClosedEventArgs e)
    {
         // My event named exit should run here, but I get exception!
        exit(100);
    }
}

Class b
{
    a instance=new a();
    a.exit+=new a.delegat(my_fun);
    ...
    private void my_fun(int x)
    {
        if(x==100)
        do_smth;
        ...
    }
}
但问题是我得到了一个异常:“对象引用未设置为对象的实例”。 我不明白我做错了什么?我应该在哪里做一个新的例子?
谢谢你的帮助

在引发事件之前,请验证是否存在任何订阅服务器:

if (exit != null)
    exit(100);
另一个选项-在类A中定义事件时订阅虚拟事件处理程序:

public event delegat exit = (_) => { };

对类型、事件和方法也使用PascalCase命名。NET中有一个预定义的委托,它接收一个参数并返回void:
Action

您试图在类本身而不是实例上分配
exit
事件,例如

应该是:

instance.exit += ...
您也不会在尝试触发
退出
事件之前检查该事件是否已分配。还有其他一些问题你没有考虑到,比如比赛条件

下面是一个相对安全的事件处理方法的一般示例,例如

public class A
{
    public delegate void ExitHandler(object sender, int a);
    public event ExitHandler Exit;
    ...
    private void a_FormClosed(object sender, FormClosedEventArgs e)
    {
        OnExit(100);
    }

    protected virtual void OnExit(int a)
    {
        // take a reference to the event (incase it changes)
        var handler = Exit;
        if (handler != null)
        {
            handler(this, a);
        }
    }

}

public class B
{
    private A _a;

    public B()
    {
        _a = new A();
        _a.Exit += (sender, value) => my_fun(value);
    }

    private void my_fun(int x)
    {
        if(x==100)
            do_smth;
        ...
    }
}
我将调用事件的“class a”代码更改为:

Class a
{
  public delegate void delegat(int a);
  public event delegat exit;
  ...
  private void a_FormClosed(object sender, FormClosedEventArgs e)
    {
     if (this.exit != null)  // just in case a_FormClosed fires before assigning the event
         exit(100);//here should run my event named exit but i get exception!
     }
}
试试这个

namespace foo
    {
    public delegate void delegat(int a);
    Class a
    {
      public event delegat exit;
      private void a_FormClosed(object sender, FormClosedEventArgs e)
        {
if(exit != null)
{
         exit(100);//here should run my event named exit but i get exception!
    }
         }
     }
    }

     Class b
     {
      a instance=new a();
      instance.exit+=new delegat(my_fun);
      ...
      priavte void my_fun(int x)
      {
       if(x==100)
        do_smth;
       ...
       }
     }

如何运行此代码?您是否创建了b的实例?您确定异常来自于与b中相同的a实例吗?您最大的问题是您在类上调用非静态方法。您创建了一个名为“instance”的实例,但从不使用它,因为您直接在a上调用所有内容。改为在“实例”上调用它们,看看会发生什么。当我按下“b”窗体上的某个按钮时,会生成“a”类的实例。然后,.ShowDialog()函数显示“a”类窗体,我在“a”窗体上执行一些操作。正如您所看到的,我的事件应该在其他事件触发时触发(“a”窗体上的formClosed事件)。可能有什么问题吗?是的,我确信异常来自以下部分:
private void a_FormClosed(object sender,FormClosedEventArgs e){exit(100);//这里应该运行名为exit的事件,但我得到异常!}
Hoeloe-我发现了这些错误:我应该这样写smth:
instance.exit+=newa.delegat(我的乐趣)
而不是
a.exit+=new a.delegat(我的乐趣)但它仍然抛出一个异常。+1,但我还建议对事件参数(从
EventArgs
继承的对象)使用约定@ken2k这可能更像是一个首选项,我更喜欢
EventArgs
,而不是委托自己。但是,使用委托没有问题。最佳做法还包括为事件/委托约定引发事件的
受保护的
方法。另一件重要的事情是事件处理程序的
对象发送者
第一个参数。@lazyberezovsky是的,但是,没有提到类作为基类公开,甚至没有提到它被继承。我通常以“实现我需要的”的方式进行开发,而不是“实现我可能需要的”-但是,作为参考,我已经更新了签名,因为无论哪种方式,它都不会影响OP尝试执行的操作:)我还更新了代理以传递发件人(good point@ken2k)
namespace foo
    {
    public delegate void delegat(int a);
    Class a
    {
      public event delegat exit;
      private void a_FormClosed(object sender, FormClosedEventArgs e)
        {
if(exit != null)
{
         exit(100);//here should run my event named exit but i get exception!
    }
         }
     }
    }

     Class b
     {
      a instance=new a();
      instance.exit+=new delegat(my_fun);
      ...
      priavte void my_fun(int x)
      {
       if(x==100)
        do_smth;
       ...
       }
     }