Передать параметр по ссылке между двумя формами - PullRequest
3 голосов
/ 21 сентября 2009

У меня есть две формы (Форма 1 и Форма 2). В Form1 есть переменная public int i, для которой в конструкторе Form1 установлено значение 1. Затем я открываю Form2 из Form1 с этим кодом:

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

Конструктор Form2 выглядит так:

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

Затем я устанавливаю переменную i в Form2 в значение 2 и закрываю Form2. Теперь я ожидаю, что переменная i в Form1 будет иметь значение 2 (из-за ключевого слова ref при передаче параметров), но все равно равно 1. Что я делаю неправильно и почему ключевое слово ref не работает в моем примере?

Спасибо

Ответы [ 8 ]

6 голосов
/ 21 сентября 2009

Что на самом деле происходит.

  1. Вы создаете объект1 с целочисленным членом с именем "i"
  2. Вы передаете ссылку на «i» в новый конструктор объекта. Ссылка на «я» называется «х».
  3. Вы копируете значение «x» во переменную во втором объекте, также называемом «i».
  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();
    }
}

Вероятно, это будет самый простой способ выполнить то, что вы собираетесь.

6 голосов
/ 21 сентября 2009

Модификатор ref имеет значение только во время самого вызова конструктора. Он связан только с этим параметром ... и после завершения конструктора этот параметр больше не существует.

При выполнении задания:

i = x;

Это просто копирование значения . Это не связывает переменную i с x любым другим способом.

Как общее практическое правило: если вы не измените значение параметра в методе / конструкторе (чего нет в вашем примере), модификатор ref ничего не сделает.

Вы не можете делать то, что хотите: вы не можете сделать поле (в данном случае Form2. i) псевдонимом другой переменной.

2 голосов
/ 21 сентября 2009

Если вы действительно хотите иметь возможность установить переменную в Form1 из Form2, вы можете использовать метод обратного вызова. (то есть передать адрес метода, который устанавливает переменную 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.

1 голос
/ 21 сентября 2009

Я согласен с Мартином, что решение такого типа добавит ненужную связь, но если вы все еще настаиваете на том, чтобы оно было связано таким образом, я думаю, что использование простого указателя поможет.

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

Не забывайте помнить об управлении памятью.

0 голосов
/ 21 сентября 2009

Спасибо за ответы ...

На данный момент я нашел три способа вернуть переменную из Form2 в Form1:

  • вместо обычного целого числа передайте объект между формами
  • в Form1 я мог бы поместить 'private int myVariable' и свойство 'public int MyVariable' с помощью методов get и set. Затем я мог бы передать всю форму Form1 конструктору Form2, где я могу получить доступ к свойству Form1.MyVariable
  • указатель

Есть ли другой вариант? Какой из этих трех вариантов лучше? (В моем примере мне нужен доступ только к одному целому числу в Form1 из Form2)

Спасибо

0 голосов
/ 21 сентября 2009

Я не знаю, почему вы так поступили, но я подозреваю, что будет гораздо лучше вернуть значение из диалоговой формы и использовать его для установки переменной в вызывающем классе. В противном случае вы бы добавили ненужные связи в свои формы.

0 голосов
/ 21 сентября 2009

область действия ref keyword находится только в пределах метода объявления: конструктор Form2. Как только этот метод завершается, i в form1 и i в form2 больше не связаны (особенно потому, что они имеют ValueType)

0 голосов
/ 21 сентября 2009
i = x;

Это утверждение копирует значение i в значение x. Чтобы изменить x, вам нужно присвоить ему значение в конструкторе. например.

x=2;
...