在闭合表格和无效后,为什么我仍然可以访问表单属性



我有一个 MainFormUserConfigForm,并使用此答案中的模式用于 UserConfigForm,即。

private static UserConfigForm openForm = null;
public static UserConfigForm GetInstance() 
{
    if (openForm == null)
    {
        openForm = new UserConfigForm();
        openForm.FormClosed += delegate { openForm = null; };
    }
    return openForm;
}

UserConfigForm内部,我也有一个自动质体UserHasSaved即。

public bool UserHasSaved { get; private set; }

现在,在MainForm中,我需要检查是否必须在关闭配置表单时重新加载用户配置。所以在MainForm中,我有

private UserConfigForm userCfgForm;
private void OpenEditFormClick(object sender, EventArgs e)
{
    userCfgForm = UserConfigForm.GetInstance();
    userCfgForm.FormClosed += ConfigFormClosed;
    userCfgForm.Show();
{
private void ConfigFormClosed(object sender, FormClosedEventArgs e)
{
    if (userCfgForm.UserHasSaved)
    {
        MessageBox.Show(message, caption);
        //Reload config
    }
}

问题在于这起作用,但我不明白为什么会这样。我有两个事件处理程序注册到FormClosed,所以我认为处理哪个订单活动处理程序是谨慎的。

看来,事件处理程序是按照注册的顺序处理的。因此,我可以在delegate { openForm = null }之后访问userCfgForm.UserHasSaved是没有意义的。

我应该为此担心还是很高兴它有效?

您对参考类型的变量在c#中的工作方式有误解。

让我们看一个更简单的示例:

class F1
{
  static int x = 0;  
  public static int Start()
  {
    x = 1;
    return x;
  }
  public static void Stop()
  {
    x = 0;
  }
}
class F2
{
  int y;
  void DoIt()
  {
    this.y = F1.Start();
    F1.Stop();
    Console.WriteLine(this.y);
  }
}

假设我们在F2实例上调用DOIT。this.y的值是多少?

通过程序的动作进行跟踪:

  • f1.x开始为零。
  • f2.doit调用f1.start()
  • f1.x变为1
  • f1.start()返回1
  • f2.y变为1
  • f2.doit调用f1.stop()
  • f1.x变为0

f2.y仍然是1.更改F2.X并没有更改有关f2.y的任何内容。这是一个完全不同的变量。我们没有创建任何一种神奇的连接,说"当您阅读f2.y时,真正读取f2.x的当前值"。

您的程序也是如此。我们可以将其更改为参考类型,没有任何更改:

class F1
{
  public static F1 x = null;  
  public static F1 Start()
  {
    x = new F1();
    return x;
  }
  public static void Stop()
  {
    x = null;
  }
}
class F2
{
  F1 y;
  void DoIt()
  {
    this.y = F1.Start();
    F1.Stop();
    Console.WriteLine(this.y == null); // false
  }
}

会发生什么?同样的事情。

  • f1.x以null。
  • 开始
  • f2.doit调用f1.start()
  • f1.x成为对有效对象的引用
  • f1.start()返回对有效对象的引用
  • f2.y成为对有效对象的引用
  • f2.doit调用f1.stop()
  • f1.x变为null

什么是f2.y?仍然是对有效对象的引用。f2.y是从不参考f1.x。它们都是对同一有效对象的引用。参考是值,就像整数一样

现在,如果您想要对变量有一个别名,则C#7让您这样做:

class F1
{
  static int x = 0;  
  public static ref int Start()
  {
    x = 1;
    return ref x;
  }
  public static void Stop()
  {
    x = 0;
  }
}
class F2
{
  void DoIt()
  {
    ref int y = ref F1.Start();
    F1.Stop();
    Console.WriteLine(y); // 0
  }
}

ref表示本地变量y是变量f1.x 的别名,因此,当我们更改F2.x时,我们还会更改y,因为它们只是两个 names 对于相同的变量;它们是 cliased

请注意,变量的别名与变量的类型无关。您可以对int变量制造一个别名,无论如何,都可以使对象变量成为一个别名。别名变量和混叠本地必须具有完全相同的类型(练习:为什么?),但是这种类型可以是您想要的。

规则是:别名变量可以是任何变量;混叠变量只能是本地或正式参数。例如,没有办法制作" ref int"字段。请注意, ref int y local ,而不是 field

返回变量别名是一个高级功能,我们多年来一直在辩论它是否正确地添加到C#。您不应使用此功能,直到您对C#中的参考语义有深入的了解。

最新更新