简体   繁体   English

C# - 无法从事件处理程序访问全局变量

[英]C# - Can't access a global variable from an event handler

I have a Windows Forms Application with a global variable - a string called testPath . 我有一个带有全局变量的Windows窗体应用程序 - 一个名为testPath的字符串。

This string is used to save a path - by default it is C:\\temp\\ . 此字符串用于保存路径 - 默认情况下为C:\\temp\\ When the user clicks a button, this directory is created (if it does not exist already). 当用户单击按钮时,将创建此目录(如果它尚不存在)。

There is also a textbox control, in case the user wants to change the value of the path. 如果用户想要更改路径的值,还有一个文本框控件。

At the button's event handler, I try to access testPath and I get a null reference. 在按钮的事件处理程序中,我尝试访问testPath并获得null引用。

I am not changing the value of testPath anywhere, except when I pass it to and from the textbox Control. 我没有在任何地方更改testPath的值,除非我将它传递给文本框Control和从文本框Control传递。

What am I doing wrong? 我究竟做错了什么? How does the global variable have something inside at one second, and then right afterwards it points to a null reference? 全局变量如何在一秒内有内容,然后在之后它指向空引用?

Here is the complete code: 这是完整的代码:

public string testPath = @"C:\temp\";

public MainForm()
{
     //Windows Designer call
     InitializeComponent();

     //Show the testPath in the textBox (using Invokes)
     this.textBox1.Invoke(new MethodInvoker(delegate { this.textBox1.Text = testPath; } ));

     //here, testPath contains 'C:\temp\'
}

//Button "Click" handler
private void Button1Click(object sender, EventArgs e)
{
     //here, testPath contains a null reference!

     //If the user changed testPath in the textBox, we need to save it again
     this.textBox1.Invoke(new MethodInvoker(delegate { testPath = this.textBox1.Text; } ));

     //Create the path
     if(!Directory.Exists(testPath)) //If it does not exist already
     {
         Directory.CreateDirectory(testPath); 
     }

     //...Do something else

}

I would suggest making this a constant: 我建议把它变成一个常数:

const string testPath = @"C:\temp\";

This will cause any attempt to set the value to be flagged as a compiler error. 这将导致任何尝试将值设置为标记为编译器错误。 Using the value will work without changes. 使用该值将无需更改即可使用。


Edit in response to comments: 编辑以回应评论:

Since you want to change the value, I would recommend reworking this as a property: 由于您想要更改该值,我建议将其重新设置为属性:

private string _testPath = @"C:\temp\";
private string testPath 
{ 
    get { return _testPath; }
    set
    {
        _testPath = value;
    }
}

You can then set a breakpoint on the line _testPath = value; 然后,您可以在行_testPath = value;上设置断点_testPath = value; , and see, in the debugger, exactly what is setting this to null . ,并在调试器中看到将此设置为null确切内容。 Once this is corrected, I would then recommend fixing the naming to match standard .NET naming conventions. 一旦纠正,我会建议修复命名以匹配标准的.NET命名约定。

I would try marking the field testPath as readonly, and follow the compiler errors. 我会尝试将字段testPath标记为只读,并遵循编译器错误。

Here's a tutorial on differences between const and readonly. 这是关于const和readonly之间差异的教程

EDIT You could look at implementing a custom handler for the form load event and inspect the state there. 编辑您可以查看为表单加载事件实现自定义处理程序并检查那里的状态。 You could also use step through using F10 as you're constructing the object, as you're handling form load event, and as you're handling user input. 您还可以在构建对象时使用F10,因为您正在处理表单加载事件,并且正在处理用户输入。 Keep in mind that when just entering the function, all variables show as uninitialized on the opening curly brace. 请记住,当刚刚进入该函数时,所有变量在开始大括号上显示为未初始化。 You'd have to step through the function at least once to see them. 您必须至少执行一次该功能才能看到它们。 Use a pin to keep an eye on your variables in the text editor. 使用引脚在文本编辑器中密切关注变量。

Updated : I am not sure why do you need this public variable. 更新 :我不确定为什么你需要这个公共变量。 If you simply want to initialize the control with some initial value like "C:\\temp\\" & user can edit it if he wants. 如果你只想用一些初始值初始化控件,比如“C:\\ temp \\”,用户可以根据需要编辑它。 If that is the case, open the form in design view, right click on textbox > go to properties. 如果是这种情况,请在设计视图中打开表单,右键单击文本框>转到属性。 In properties window, change the Text property to "C:\\temp\\", after you are done with this, your text box will be initialized with "C:\\temp\\". 在属性窗口中,将Text属性更改为“C:\\ temp \\”,完成此操作后,将使用“C:\\ temp \\”初始化文本框。 In event handler you can simply write 在事件处理程序中,您只需编写

private void button1_Click(object sender, EventArgs e)
{
     if (!Directory.Exists(this.textBox1.Text.Trim()))
        {
            Directory.CreateDirectory(this.textBox1.Text.Trim());
        }

}

Original : testPath variable is getting modified to null after the Form is initialized but before the button is clicked. 原始 :在初始化Form但在单击按钮之前,testPath变量被修改为null。 Since, it is a public variable, it can be accessed & modified from outside the class as well. 因为它是一个公共变量,所以也可以从类外部访问和修改它。

One easy way to reproduce this issue - In Program class > Main method 重现此问题的一种简单方法 - 在Program类> Main方法中

[STAThread]
static void Main()
{
   Form1 obj = new Form1();
   obj.testPath = null;
   Application.Run(obj);
}

Suggestions: 1. Make testPath constant or read-only to determine if it is being modified. 建议:1。使testPath保持常量或只读以确定它是否被修改。 2. Change access specifier to private if you do not need to expose it. 2.如果您不需要公开访问说明符,请将访问说明符更改为私有。

I would suggest that instead of declaring the path outside the scope of your button click event, you declare it inside the method. 我建议您不要在按钮单击事件范围之外声明路径,而是在方法内声明它。

Like so: 像这样:

private void Button1Click(object sender, EventArgs e) 
{ 
     string testPath = @"C:\temp\"; 

     //Create the path if it does not exist      
     if(!Directory.Exists(testPath))      
          Directory.CreateDirectory(testPath);       
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM