c # неожиданное изменение значения - остерегайтесь отладчика - PullRequest
0 голосов
/ 10 января 2019

C # на Visual studio 2017.

Я создал свой класс и создал экземпляр объекта этого класса. В классе есть только два поля закрытых значений с двумя свойствами для доступа к ним и один закрытый флаг (bool). Проблема в том, что установленный метод доступа свойства касается только его (только логически) связанного поля и флага, но во время выполнения, когда я "вызываю" установленный метод доступа этого свойства, ВСЕ поля затрагиваются.

В моей реализации у меня есть только форма только с кнопкой: нажатие кнопки увеличивает значение первого поля, используя его свойство.

Мой код.

public class DriveMeCrazyClass
{        
    public double _num; // a number
    public double _dou; // his double        
    public bool dou_isValid; // I'll really update the field value only on a request.

    // The idea is: 
    // _num e _dou are related, so when _num changes 
    //    I should calculate the new value for _dou.
    // BUT
    // I prefer to postpone the calculation 
    //    to the moment when I will be asked for the value
    // SO
    // I only "take note" of this fact on the flag dou_isValid

    public DriveMeCrazyClass()
    {
        _num = _dou = 0;
        dou_isValid = true;
    }

    public event EventHandler DMCCchanged;
    public double Num
    {
        get { return _num; }

        set
        {
            if (_num == value) return;
            _num = value;                
            dou_isValid = false;                

            DMCCchanged?.Invoke(this, EventArgs.Empty);
        }
    }

    public double Dou
    {
        get
        {
            if (dou_isValid) return _dou;
            dou_isValid = true;
            DMCCchanged?.Invoke(this, EventArgs.Empty);
            return _dou = 2 * _num;
        }
        set
        {                
            // ..... no matter now
        }
    }
}




public partial class Form1 : Form
{        
    public DriveMeCrazyClass aa = new DriveMeCrazyClass();        

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        aa.DMCCchanged += new System.EventHandler(aa_changed);
        lblNum.Text = "0";
        lblDou.Text = "0";

    }

    private void Num_inc_Click(object sender, EventArgs e)
    {
        aa.Num++;
    }

    private void aa_changed(object sender, EventArgs e)
    {
        lblNum.Text = aa._num.ToString();
        lblDou.Text = aa._dou.ToString();
    }
}

Это похоже на то, как компилятор вызывает метод доступа get свойства Dou. Я не знаю почему. Оптимизация? Или что? На самом деле, я не понимаю. Кто-нибудь может мне помочь?

***** EDIT ******

Я надеваю новый код, немного изменившийся. _num и _dou теперь общедоступны, и я добавил две метки, чтобы показать их значения - без использования методов доступа Num e Dou.

без отладки: отлично работает!

НО

если я поставлю точку останова на Num.set и продолжу шаг за шагом - ПРОСМОТР Значения Num и Dou - это беспорядок !! Отладчик вызывает метод доступа Dou.get, обновляет значение _dou и устанавливает значение true в флаг dou_isValid. Я знаю, я справлюсь с этим.

Хорошо, теперь понятно! Спасибо Робин, спасибо Камило, спасибо всем, правда.

Кстати ... Эта проблема является частью более крупной проблемы, связанной с bindig. Я надеюсь, что смогу решить основную проблему сейчас, иначе .... (это угроза для вашего свободного времени :))

Ответы [ 2 ]

0 голосов
/ 10 января 2019

Это похоже на то, как компилятор вызывает метод доступа get свойства Dou. Я не знаю почему.

Не компилятор, а отладчик. Когда вы смотрите на свойства вашего класса, он получает значения всех свойств, которые выполняет код.

Методы не запускаются отладчиком, поэтому это будет работать:

double GetDou()
{
    if (dou_isValid) return _dou;
    dou_isValid = true;
    return _dou = 3 * _num;
}
0 голосов
/ 10 января 2019

Попробуйте так:

dou => num*2;

здесь dou - это свойство, подобное num, но оно автоматически устанавливается при значении num.

Edit: по моему мнению, вы должны сделать это таким образом, потому что вы сэкономите много операций присваивания, много проверок и много строк кода. Если вы хотите проверить число перед тем, как назначить его, проверьте его перед назначением num.

num = (booleanChecker) ? newNum : num;

РЕДАКТИРОВАТЬ 2: Я понял, что вы пытаетесь сделать, и вот мое решение вашей проблемы:

dou => (booleanChecker) ? num*2 : dou;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...