C# 为什么;这";指向类而不是类对象?

C# 为什么;这";指向类而不是类对象?,c#,winforms,class,events,this,C#,Winforms,Class,Events,This,假设我有两个WinForms:Form1类的f1和Form2类的f2。我想做的是:通过单击f1上的按钮1,应用程序将处理f1并运行f2。代码如下: //Form1 public partial class Form1 : Form { public Form1() { InitializeComponent; } public delegate void EH_ChangeForm(object sender, EventArgs e); //this defines

假设我有两个WinForms:Form1类的f1和Form2类的f2。我想做的是:通过单击f1上的按钮1,应用程序将处理f1并运行f2。代码如下:

//Form1
public partial class Form1 : Form
{
  public Form1()
  {
    InitializeComponent;
  }
  public delegate void EH_ChangeForm(object sender, EventArgs e);
  //this defines an event
  public static event EH_ChangeForm ChangeForm;
  private void button1_Click(object sender, EventArgs e)
  {
    //this raises the event
    ChangeForm(this, new EventArgs()); //  NRC happens here!!! Zzz~
  }
}

//Program
static class Program
{
  static Form1 f1;
  static Form2 f2;

  [STAThread]
  static void Main()
  {
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    f1 = new Form1();
    f2 = new Form2();
    Application.Run(f1);
    //this subscribers to the event
    Form1.ChangeForm += Form1_ChangeForm;
  }

  static void Form1_ChangeForm(object sender, EventArgs e)
  {
    f1.Dispose();
    Application.Run(f2);
  }
}

问题是:通过单击按钮1,程序在试图引发事件时(行“ChangeForm(this,new EventArgs());”)会变得很糟糕。发生NullReferenceException时,“this”指向Form1而不是f1


更一般地说,我应该如何在类之间使用事件?i、 例如,一个类对象应该如何订阅由另一个类对象引发的事件?

您得到
NullReferenceException
的原因是没有事件处理程序注册到您的
Form1.ChangeForm
,因为Application.Run等待实例f1停止接收消息

您需要交换Main方法中的两行,如下所示:

 Form1.ChangeForm += Form1_ChangeForm;
 Application.Run(f1);
始终尝试“尽可能快地”注册事件处理程序,这样您就不会执行某些操作,也不会期望在无人侦听时执行事件

此外,在编写事件invocators时,请尝试使用缓存事件然后调用它的模式

private void FireChangeForm() {
    var handler = ChangeForm;
    if (handler != null) {
        handler(this, new EventArgs());
    }
}

所以你也要避免任何比赛条件。请阅读Eric Lippert的博客文章,了解您为什么要这样做。

您根本不需要担心如何处理,也不应该使用
应用程序。运行
打开表单,有
Show
ShowDialog
可以这样做。不清楚您所说的“this”指的是表单1,而不是f1。“还不清楚为什么您选择创建自己的委托类型,其签名与
EventHandler
完全相同,
表示当前实例。如果不将局部类与静态类、静态事件和显式随机处理混合在一起,所有这些都将更容易调试。是什么导致了NRE?@Jon Skeet:我想传输的是一个对象,但“this”指向类,而不是对象。这个程序只是一个测试,为了简单起见,我没有定义任何特殊的委托。它可以工作。多谢各位@帕特里克:谢谢你的解释,我真的很感激!