我有一个MainForm
和一个UserConfigForm
,并将Can I escape html special chars in javascript?答案中的模式用于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
注册了两个事件处理程序,因此我决定检查事件处理程序的处理顺序是明智的。
似乎事件处理程序按照其注册顺序进行处理。因此我无法在userCfgForm.UserHasSaved
之后访问delegate { openForm = null }
。
我应该为此担心还是高兴吗?
答案 0 :(得分:8)
对于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
的值是什么?
通过程序的动作进行跟踪:
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
}
}
会发生什么?一样。
什么是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
,因为它们只是相同变量的两个名称;他们被别名。
请注意,变量的别名与变量的类型无关。您可以为int变量创建别名,也可以为对象变量创建别名。别名变量和别名局部变量必须具有完全相同的类型(运动:为什么?),但是该类型可以是您想要的任何类型。
但是规则是:别名变量可以是任何变量;别名变量只能是局部或形式参数。例如,无法创建“ ref int”字段。请注意,ref int y
是 local ,而不是 field 。
返回变量别名是一项高级功能,我们多年来一直在争论是否应将其添加到C#中。 除非您对C#中的引用语义有透彻和深入的了解,否则不要使用此功能。