_Q12_ Ответов: 2

Проблема внешнего класса


Прочтите комментарии к коду ...........................

Что я уже пробовал:

//external class
public class DCPS
{
    public string pin1_Sign = "+";
    public string pin2_Sign = "-";
    public double pin1_Volts = 3;
    public double pin2_Volts = 0;

    public void Pin1Contact(string pinXsign, double pinXvolts)
    {
        pinXsign = pin1_Sign; pinXvolts = pin1_Volts;
    }
}



public UserControl1()
{
    InitializeComponent();
    //this is NOT working
    //led.pin1_Sign is NOT changing to "+" and
    //led.pin1_Volts is NOT changing to 3
  dcps.Pin1Contact(led.pin1_Sign,led.pin1_Volts); //?????
    led.pin1_Sign = dcps.pin1_Sign; //(test) this is working fine
}
DCPowerSupply1.DCPS dcps = new DCPS();

2 Ответов

Рейтинг:
18

OriginalGriff

Нет. Этого не будет.
Это происходит потому, что все параметры, передаваемые в C#, если не указано иное, передаются по значению, а не по ссылке.

Чтобы объяснить, подумайте вот о чем:

public void TimesTwo(int x)
   {
   x = x + x;
   }
...
   int value = 666;
   TimesTwo(value);
   Console.WriteLine(value);
Если значение передавалось по ссылке (то есть x внутри метода был той же переменной, что и значение вне метода), то консоль выводила "1332".

Но... а что если я назову это так:
TimesTwo(666);
Console.WriteLine(666);
Что бы вы ожидали увидеть на консоли? "1332" или "666"?
Совершенно очевидно, что мы хотим, чтобы консоль напечатала "666", потому что в противном случае константы больше не являются постоянными, и остальной наш код станет невозможным следовать!

Таким образом, C# передает значение, а не ссылку: создается копия содержимого переменной и передается методу. Поскольку TimesTwo изменяет копию, она не влияет на внешний мир, и константы остаются теми же.

То же самое происходит со строками: копия строки передается методу, и ваш код "модифицирует" эту копию, а копия отбрасывается при выходе из метода.
Кроме... со строками все еще хуже, потому что строки неизменяемы: как только вы создаете строку в C#, ее вообще нельзя изменить - каждый раз, когда вы пытаетесь, вы создаете новую строку, и они оба затем существуют бок о бок.

Если вы хотите передать значение обратно, вы можете ... но вы должны указать это при создании и использовании метода:
public void Pin1Contact(out string pinXsign, out double pinXvolts)
    {
        pinXsign = pin1_Sign; pinXvolts = pin1_Volts;
    }

dcps.Pin1Contact(out led.pin1_Sign, out led.pin1_Volts);

Это говорит системе возвращать параметры по ссылке, а не по значению.
Вы также можете использовать ref вместо этого используйте ключевое слово, и система также позволит вам получить доступ к текущему значению в методе:
public void Pin1Contact(ref string pinXsign, ref double pinXvolts)
    {
        pinXsign += pin1_Sign; pinXvolts += pin1_Volts;
    }

dcps.Pin1Contact(ref led.pin1_Sign, ref led.pin1_Volts);


_Q12_

Вааааа !!! Большое вам спасибо !
Я знал о существовании out и ref, но никогда не знал, когда их использовать!
Теперь, благодаря тебе, я знаю. ОЧЕНЬ ХОРОШЕЕ ОБЪЯСНЕНИЕ !!!!!!!!
Дополнительный вопрос: а если я хочу конкретно передать значение, то какое ключевое слово я должен использовать?

OriginalGriff

Его нет: это значение по умолчанию, поэтому, если вы не укажете out или ref, оно будет по значению.

_Q12_

Спасибо,
Теперь я понимаю.
Такое хорошее объяснение ! Охоа! 10+++++++++
Живите долго и процветайте !

OriginalGriff

Всегда пожалуйста!

Рейтинг:
1

Richard MacCutchan

Вы не можете изменить значения led таким образом. Вы просто меняете значения локальных переменных параметров. Ваш дизайн класса и его использование неверны. То Pin1Contact метод должен использоваться для изменения значений переменных объекта, а не каких-то внешних. Это должно быть как:

public class DCPS
{
    public string pin1_Sign = "+";
    public string pin2_Sign = "-";
    public double pin1_Volts = 3;
    public double pin2_Volts = 0;

    public void Pin1Contact(string pinXsign, double pinXvolts)
    {
        pin1_Sign = pinXsign;
        pin1_Volts = pinXvolts
    }
}

led.Pin1Contact("-", 5.0);


_Q12_

Спасибо. Вы тоже правы!

Richard MacCutchan

Рад помочь.