3

2つのフォーム(Form1とForm2)があります。Form1には、Form1コンストラクターで値1に設定されている'publicinti'変数があります。次に、次のコードを使用してForm1からForm2を開きます。

Form2 f2 = new Form2(ref i);
f2.ShowDialog();

Form2のコンストラクターは次のようになります。

public int i;
public Form2(ref int x)
{
    InitializeComponent();
    i = x;
}

次に、Form2の変数iを値2に設定し、Form2を閉じます。これで、Form1の変数iの値が2になると予想されますが(パラメーターを渡すことによる'ref'キーワードのため)、値は1のままです。何が間違っているのでしょうか。また、私の例ではrefキーワードが機能しないのはなぜですか。

ありがとう

4

8 に答える 8

6

「ref」修飾子は、コンストラクター呼び出し自体の間にのみ違いをもたらします。それはそのパラメーターにのみ関連付けられています...そしてコンストラクターが終了した後、そのパラメーターはもう存在しません。

割り当てを実行する場合:

i = x;

これは、値をコピーするだけです。変数ix他の方法で関連付けることはありません。

一般的な経験則として、メソッド/コンストラクター内でパラメーターの値を変更しない場合(この例では変更しません)、ref修飾子は何もしません。

やりたいことをすることはできません。フィールドi(この場合はForm2 )を他の変数のエイリアスにすることはできません。

于 2009-09-21T12:37:40.060 に答える
6

実際に何が起こっているのか。

  1. 「i」という名前の整数メンバーを使用してobject1を作成します
  2. 「i」への参照を新しいオブジェクトコンストラクターに渡します。「i」への参照は「x」と呼ばれます。
  3. 「x」の値を、「i」とも呼ばれる2番目のオブジェクトの変数にコピーします。
  4. object2のコンストラクターを終了します。object1.iへの参照はここで終了します。
  5. object2.iを変更します(これはobject1.iのコピーですが、参照、ポインター、またはリンクではありません)。object1.iは変更されません。

イベントを使用するか、object1とobject2の間で共有されるオブジェクトを渡すことによって、目的を達成する方法はたくさんあります。

Class Form1
{
    Object i = new Object();
    ...
    public void DoSomething()
    {
        Form2 f = new Form2(i);
        f.Show();
    }
}

これはおそらくあなたが目指していることを達成するための最も簡単な方法でしょう。

于 2009-09-21T12:44:32.030 に答える
2

私はマーティンに同意します。このタイプのソリューションは不要な結合を追加しますが、それでもこのように結び付けることを主張する場合は、単純なポインターを使用することでうまくいくと思います。

class Form1 {  
  public int i;
  public void doSomething(){
    Form2 f = new Form2(&i);
    f.showDialog();
  }
}

次に、Form2では、そのポインターを操作するだけです。

class Form2 {
  public int *i;
  public Form2(int *r){
    InitializeComponent();
    i = r;
  }
  public void setI(int v){
    *i = v;
  }
  public int getI(){
    return *i;
  }
}

これらすべてでメモリ管理を覚えておいてください。

于 2009-09-21T13:50:19.710 に答える
2

Form2内からForm1に変数を設定できるようにしたい場合は、コールバックメソッドを使用できます。(つまり、Form1変数を設定してForm2から実行するメソッドのアドレスを渡します)

このようなもの:

public partial class Form1 : Form
{
    public delegate void FormReturn(string s);
    private string var1;

    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        var frm = new Form2(ReturnFunc);
        frm.ShowDialog();
    }

    protected void ReturnFunc(string text)
    {
        var1 = text;
    }
}

public partial class Form2 : Form
{
    private Form1.FormReturn returnFunc;

    public Form2(Form1.FormReturn del)
    {
        InitializeComponent();
        returnFunc = del;
    }

    private void btnClose_Click(object sender, EventArgs e)
    {
        returnFunc.Invoke(txtText.Text);
        Close();
    }
}

しかし、大きなやり過ぎ。form1にパブリックプロパティを設定するだけです。

于 2009-09-21T16:08:18.387 に答える
0
i = x;

このステートメントは、iの値をxの値にコピーしています。xを変更するには、コンストラクターで実際に値を割り当てる必要があります。例えば。

x=2;
于 2009-09-21T12:39:21.657 に答える
0

スコープは、ref keyword宣言メソッドであるForm2コンストラクター内にのみ存在します。そのメソッドが終了すると、form1のiとform2のiはリンクされなくなります(特にValueTypeであるため)

于 2009-09-21T12:41:02.263 に答える
0

そのようにする理由はわかりませんが、ダイアログフォームから値を返し、それを使用して呼び出し元のクラスに変数を設定する方がはるかに良いと思います。そうしないと、フォームに不要なカップリングを追加することになります。

于 2009-09-21T12:49:15.310 に答える
0

答えてくれてありがとう...

今のところ、Form2からForm1に変数を戻す方法を3つ見つけました。

  • 通常の整数の代わりに、フォーム間でオブジェクトを渡します
  • Form1では、getメソッドとsetメソッドを使用して「privateintmyVariable」とプロパティ「publicintMyVariable」を配置できます。次に、Form1全体をForm2のコンストラクターに渡して、Form1.MyVariableプロパティにアクセスできます。
  • ポインタ

他に選択肢はありますか?この3つのオプションのどれが良いですか?(私の例では、Form2からForm1の1つの整数にのみアクセスする必要があります)

ありがとう

于 2009-09-21T13:52:19.893 に答える