我有一个MainForm和一个UserConfigForm并使用了这个答案中的模式UserConfigForm即
private static UserConfigForm openForm = null;
public static UserConfigForm GetInstance()
{
if (openForm == null)
{
openForm = new UserConfigForm();
openForm.FormClosed += delegate { openForm = null; };
}
return openForm;
}
Run Code Online (Sandbox Code Playgroud)
在里面UserConfigForm我也有一个自动财产UserHasSaved即
public bool UserHasSaved { get; private set; }
Run Code Online (Sandbox Code Playgroud)
现在在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
}
}
Run Code Online (Sandbox Code Playgroud)
问题是这有效,但我不明白为什么会这样.我注册了两个事件处理程序,FormClosed所以我决定检查处理事件处理程序的顺序是谨慎的.
事件处理程序似乎按照它们的注册顺序进行处理.所以它不会使我可以访问的意义userCfgForm.UserHasSaved之后delegate { openForm = null }.
我应该担心这个还是只是对它的工作感到高兴?
关于引用类型的变量如何在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);
}
}
Run Code Online (Sandbox Code Playgroud)
假设我们在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
}
}
Run Code Online (Sandbox Code Playgroud)
怎么了?一样.
什么是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
}
}
Run Code Online (Sandbox Code Playgroud)
该ref方法本地变量y的别名变量F1.X,所以当我们改变F2.x,我们改变y还,因为他们只是两个名称为同一个变量 ; 他们是别名.
请注意,变量的别名与变量的类型无关.您可以为int变量创建别名,您可以为对象变量创建别名,无论如何.别名变量和别名本地必须具有完全相同的类型(练习:为什么?)但该类型可以是您想要的任何类型.
但规则是:别名变量可以是任何变量; 别名变量只能是本地或形式参数.例如,没有办法制作"ref int"字段.请注意,这ref int y是一个本地,而不是一个字段.
返回变量别名是一个高级功能,我们多年来一直争论是否适合添加到C#.在对C#中的引用语义进行全面深入理解之前,不应使用此功能.