Как я могу инициализировать события с делегатами, которые включают значения времени выполнения? - PullRequest
0 голосов
/ 16 ноября 2018

Я столкнулся с этой проблемой, когда пытался назначить набор событий с набором действий делегата.Если я использую функцию AssignEventsManually(), события запускают назначенных им делегатов с правильной информацией (разные номера).Когда я использую цикл для выполнения этих назначений, все кнопки печатают одинаковое значение «B2».

Кажется, что сам делегат хранится в куче, но номер итерации i находится в стеке, и каждый делегат ссылается на один и тот же элемент.Как я могу добиться назначения каждого делегата с его собственным экземпляром итератора?

using System.Windows.Forms;

namespace DelegatesTest
{
    public partial class Form1 : Form
    {
        Button[] bar;                

        public Form1()
        {
            InitializeComponent();

            bar = new Button[] { button1, button2, button3 };

            for (int i=0; i<3; i++)
            {                                
                bar[i].Click += delegate
                {                    
                    richTextBox1.Text = $"B{i}";
                };                               
            }

            //AssignEventsManually();
        }

        void AssignEventsManually()
        {            
            button1.Click += delegate
            {
                richTextBox1.Text = $"b{1}";
            };            
            button2.Click += delegate
            {                
                richTextBox1.Text = $"b{2}";
            };            
            button3.Click += delegate
            {                
                richTextBox1.Text = $"b{3}";
            };            
        }

    }
}

1 Ответ

0 голосов
/ 16 ноября 2018

Кажется, что сам делегат хранится в куче, но номер итерации "i" находится в стеке, и каждый делегат ссылается на один и тот же элемент. Как я могу добиться назначения каждого делегата с его собственным экземпляром итератора?

i здесь «захваченная» переменная, которая находится в куче в классе контекста. Контекстный класс имеет такую ​​же область действия, что и i, то есть: на время цикла

Чтобы исправить это: создайте снимок копии i внутри цикла.

for (int i=0; i<3; i++)
{
    int cpy = i;
    bar[i].Click += delegate
    {                    
        richTextBox1.Text = $"B{cpy}";
    };   
}

Или, возможно, более эффективно:

for (int i=0; i<3; i++)
{
    string txt = $"B{i}";
    bar[i].Click += delegate
    {                    
        richTextBox1.Text = txt;
    };
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...