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.

This string is used to save a path - by default it is 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.

I am not changing the value of testPath anywhere, except when I pass it to and from the textbox 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

}

Answers


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;, and see, in the debugger, exactly what is setting this to null. Once this is corrected, I would then recommend fixing the naming to match standard .NET naming conventions.


I would try marking the field testPath as readonly, and follow the compiler errors.

Here's a tutorial on differences between const and 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. 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. 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\". 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. 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

[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. 2. Change access specifier to private if you do not need to expose it.


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);       
}

Need Your Help

How to mark session as non-bounce in Google Analytics

ajax google-analytics

I understand that Google Analytics takes a user session as a "Bounce" if the user visits one page and no more.

How can I know if an element is a direct child of the body using jQuery

jquery dom traversal

I want to perform some action on elements that are not direct child of the body. How can I check a particular element to know whether its partent is the body.