Привязка метода к событию в C # с помощью = operator

#c# #events

#c# #Мероприятия

Вопрос:

Я создавал форму Windows и пытался вручную привязать метод к событию click в MyButton, вот так:

     public Form1()
    {
        InitializeComponent();
        myButton.Click = new EventHandler(ShowMessage("You clicked my button!"));
    }

    private void ShowMessage(string message)
    {
        MessageBox.Show(message);
    }
  

Как некоторые из вас могут догадаться, компилятору это не понравилось. Я не был уверен, почему, потому что я привык к тому, что могу делать такие вещи в Javascript, как это:

 document.getElementById("myButton").onclick = function(){showMessage("You clicked my button")};
function showMessage(message) {
  alert(message);
}
  

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

     string message = "";
    public Form1()
    {
        InitializeComponent();
        message = "You clicked my button!";
        myButton.Click  = ShowMessage; 
    }

    private void ShowMessage(object sender, EventArgs e)
    {
        MessageBox.Show(message);
    }
  

Вот мои два вопроса: во-первых, есть ли более чистый способ сделать это? Во-вторых, почему методы событий должны назначаться с помощью = , а не просто = ?

Комментарии:

1. Попробуйте csharpcomputing.com/Tutorials/Lesson15.htm

Ответ №1:

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

Кроме того, вы, вероятно, захотите воспользоваться преимуществами анонимных делегатов для выполнения любой формы привязки аргументов. Например:

 myButton.Click  = delegate(object sender, EventArgs e) {
    MessageBox.Show("You clicked my button!");
};
  

Ответ №2:

Вы также можете использовать lambda.

 myButton.Click  = (sender, e) => {
    MessageBox.Show("You clicked my button!");
};
  

Ответ №3:

Вот мои два вопроса: во-первых, есть ли более чистый способ сделать это?

да, анонимные функции, как и в JavaScript (другой синтаксис)

 myButton.Click  = delegate(object sender, EventArgs e)   
{ 
  MessageBox.Show(message);
};  
  

почему методы событий должны быть
назначается с помощью =, а не просто =?

В противном случае у вас может быть только 1 обработчик событий вместо нескольких для одного и того же события. = часто используется в языке программирования для добавления чего-либо. = используется для присвоения переменной значения.

Комментарии:

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

Ответ №4:

Вы можете ввести myButton.Click = delegate { showmessage("You clicked my button!"); };

Ответ №5:

Поскольку может быть добавлено более одного обработчика, как в вашем коде javascript, в onclick будет вызываться только одна функция.

Пример:

 myButton.Click  = ShowMessage;
myButton.Click  = LogToFile;
  

Обе функции ShowMessage и LogToFile будут вызываться при нажатии кнопки. Именно это пытается указать » » в » =». Вы добавляете к обработчику, а не заменяете его.

Что касается упрощения, вы могли бы использовать анонимные lamda, чтобы помочь like, но обратите внимание, что это затрудняет отсоединение / удаление обработчиков позже (если это важно).

 myButton.Click  = new EventHandler( (sender,e) => ShowMessage("You clicked my button!") );
  

Ответ №6:

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

 private void ShowMessage(object sender, EventArgs e, string message)
{
    MessageBox.Show(message);
}


public Form1()
{
    InitializeComponent();
    myButton.Click  = delegate(object sender, EventArgs e)   
    { 
        ShowMessage(sender,e,"You clicked my button!");
    };  
}