2

グローバル変数を持つ Windows フォーム アプリケーションがありますtestPath

この文字列は、パスを保存するために使用されます。デフォルトではC:\temp\. ユーザーがボタンをクリックすると、このディレクトリが作成されます (まだ存在しない場合)。

ユーザーがパスの値を変更したい場合に備えて、テキスト ボックス コントロールもあります。

ボタンのイベント ハンドラでアクセスしようとするtestPathと、null 参照が返されます。

testPathテキストボックスコントロールとの間で値を渡す場合を除いて、どこの値も変更していません。

私は何を間違っていますか?グローバル変数が 1 秒で内部に何かを持ち、その後すぐに null 参照を指すのはなぜですか?

完全なコードは次のとおりです。

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

}
4

4 に答える 4

8

これを定数にすることをお勧めします:

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

これにより、値を設定しようとすると、コンパイラ エラーとしてフラグが立てられます。値を使用すると、変更なしで機能します。


コメントに応じて編集:

値を変更したいので、これをプロパティとして作り直すことをお勧めします。

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

次に、行にブレークポイントを設定_testPath = value;し、デバッガーで、これを に設定しているものを正確に確認できますnull。これが修正されたら、標準の .NET 命名規則に一致するように命名を修正することをお勧めします。

于 2012-06-14T16:48:14.993 に答える
3

フィールドを読み取り専用としてマークしてtestPath、コンパイラエラーを追跡してみます。

これは、constとreadonlyの違いに関する チュートリアルです。

編集フォームロードイベントのカスタムハンドラーの実装を検討し、そこで状態を調べることができます。オブジェクトを作成するとき、フォームのロードイベントを処理するとき、およびユーザー入力を処理するときに、F10を使用してステップスルーを使用することもできます。関数に入ると、すべての変数が最初の中括弧で初期化されていないものとして表示されることに注意してください。それらを表示するには、少なくとも1回は関数をステップ実行する必要があります。ピンを使用して、テキストエディタで変数を監視します。

于 2012-06-14T16:47:23.017 に答える
1

更新: なぜこのパブリック変数が必要なのかわかりません。「C:\temp\」のような初期値でコントロールを初期化するだけの場合、ユーザーは必要に応じて編集できます。その場合は、フォームをデザイン ビューで開き、テキスト ボックスを右クリックして [プロパティ] に移動します。プロパティ ウィンドウで、Text プロパティを「C:\temp\」に変更します。これが完了すると、テキスト ボックスは「C:\temp\」で初期化されます。イベントハンドラでは、単純に書くことができます

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

}

オリジナル: フォームが初期化された後、ボタンがクリックされる前に、testPath 変数が null に変更されています。これはパブリック変数であるため、クラス外からもアクセスおよび変更できます。

この問題を再現する簡単な方法の 1 つ - Program クラス > Main メソッド内

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

提案: 1. testPath を定数または読み取り専用にして、変更されているかどうかを判断します。2.公開する必要がない場合は、アクセス指定子をプライベートに変更します。

于 2012-06-14T17:13:32.653 に答える
0

ボタン クリック イベントのスコープ外でパスを宣言する代わりに、メソッド内で宣言することをお勧めします。

そのようです:

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);       
}
于 2012-06-14T16:46:14.837 に答える