Как удалить обработчик событий лямбды [дубликат]

Взгляните на следующий ссылка также, который был также подобной проблемой с hp мини-нетбуком.

223
задан Community 23 May 2017 в 02:34
поделиться

1 ответ

В спецификации C # прямо указано (IIRC), что если у вас есть две анонимные функции (анонимные методы или лямбда-выражения), она может создавать или не создавать равные делегаты из этого кода. (Два делегата равны, если они имеют одинаковые цели и относятся к одним и тем же методам.)

Конечно, вам нужно запомнить используемый вами экземпляр делегата:

EventHandler handler = (s, e) => MessageBox.Show("Woho");

button.Click += handler;
...
button.Click -= handler;

(Я не могу найти соответствующий бит спецификации, но я был бы очень удивлен, увидев, что компилятор C # агрессивно пытается создать равные делегаты. Было бы определенно неразумно полагаться на него.)

Если вы не хотите этого делать, вам понадобится для извлечения метода:

public void ShowWoho(object sender, EventArgs e)
{
     MessageBox.Show("Woho");
}

...

button.Click += ShowWoho;
...
button.Click -= ShowWoho;

Если вы хотите создать обработчик событий, который удаляет себя с помощью лямбда-выражения, это немного сложнее - вам нужно обратиться к делегату внутри самого лямбда-выражения, и вы можете ' Сделайте это с помощью простого «объявить локальную переменную и присвоить ей с помощью лямбда-выражения», потому что тогда переменная не будет назначена определенно. Обычно это обходится путем присвоения переменной сначала нулевого значения:

EventHandler handler = null;
handler = (sender, args) =>
{
    button.Click -= handler; // Unsubscribe
    // Add your one-time-only code here
}
button.Click += handler;

К сожалению, это даже не просто инкапсулировать в метод, потому что события не представлены четко. Ближайшее, что вы могли бы сделать, было бы примерно таким:

button.Click += Delegates.AutoUnsubscribe<EventHandler>((sender, args) =>
{
    // One-time code here
}, handler => button.Click -= handler);

Даже это было бы сложно реализовать в Delegates.AutoUnsubscribe , потому что вам нужно было бы создать новый EventHandler (который был бы просто аргумент универсального типа). Выполнимо, но беспорядочно.

Обычно это обходится путем присвоения переменной сначала нулевого значения:

EventHandler handler = null;
handler = (sender, args) =>
{
    button.Click -= handler; // Unsubscribe
    // Add your one-time-only code here
}
button.Click += handler;

К сожалению, это даже не просто инкапсулировать в метод, потому что события не представлены четко. Ближайшее, что вы могли бы сделать, было бы примерно таким:

button.Click += Delegates.AutoUnsubscribe<EventHandler>((sender, args) =>
{
    // One-time code here
}, handler => button.Click -= handler);

Даже это было бы сложно реализовать в Delegates.AutoUnsubscribe , потому что вам нужно было бы создать новый EventHandler (который был бы просто аргумент универсального типа). Выполнимо, но беспорядочно.

Обычно это обходится путем присвоения переменной сначала нулевого значения:

EventHandler handler = null;
handler = (sender, args) =>
{
    button.Click -= handler; // Unsubscribe
    // Add your one-time-only code here
}
button.Click += handler;

К сожалению, это даже не просто инкапсулировать в метод, потому что события не представлены четко. Ближайшим к вам может быть что-то вроде:

button.Click += Delegates.AutoUnsubscribe<EventHandler>((sender, args) =>
{
    // One-time code here
}, handler => button.Click -= handler);

Даже это будет сложно реализовать в Delegates.AutoUnsubscribe , потому что вам придется создать новый EventHandler (который будет просто аргумент универсального типа). Выполнимо, но беспорядочно.

d необходимо создать новый EventHandler (который будет просто аргументом универсального типа). Выполнимо, но беспорядочно.

d необходимо создать новый EventHandler (который будет просто аргументом универсального типа). Выполнимо, но беспорядочно.

320
ответ дан 23 November 2019 в 04:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: