c object sender что такое
Что такое событие?
Событием в языке C# называется сущность, предоставляющая две возможности: для класса — сообщать об изменениях, а для его пользователей — реагировать на них.
Пример объявления события:
Рассмотрим, из чего состоит объявление. Сначала идут модификаторы события, затем ключевое слово event, после него — тип события, который обязательно должен быть типом-делегатом, и идентификатор события, то есть его имя. Ключевое слово event сообщает компилятору о том, что это не публичное поле, а специальным образом раскрывающаяся конструкция, скрывающая от программиста детали реализации механизма событий. Для того, чтобы понять, как работает этот механизм, необходимо изучить принципы работы делегатов.
Основа работы событий — делегаты
События — реализация по умолчанию
Рассмотрим наиболее часто используемую реализацию событий — неявную. Пусть имеется следующий исходный код на языке C# 4 (это важно, для более ранних версий генерируется несколько иной код, о чем будет рассказано далее):
Эти строчки будут транслированы компилятором в код, аналогичный следующему:
Блок add вызывается при подписке на событие, блок remove — при отписке. Эти блоки компилируются в отдельные методы с уникальными именами. Оба этих метода принимают один параметр — делегат типа, соответствующего типу события и не имеют возвращаемого значения. Имя параметра всегда ”value”, попытка объявить локальную переменную с таким именем приведет к ошибке компиляции. Область видимости, указанная слева от ключевого слова event определяет область видимости этих методов. Также создается делегат с именем события, который всегда приватный. Именно поэтому мы не можем вызвать событие, реализованное неявным способом, из наследника класса.
Interlocked.CompareExchange выполняет сравнение первого аргумента с третьим и если они равны, заменяет первый аргумент на второй. Это действие потокобезопасно. Цикл используется для случая, когда после присвоения переменной comparand делегата события и до выполнения сравнения другой поток изменяет этот делегат. В таком случае Interlocked.CompareExchange не производит замены, граничное условие цикла не выполняется и происходит следующая попытка.
Объявление с указанием add и remove
При явной реализации события программист объявляет делегат-поле для события и вручную добавляет или удаляет подписчиков через блоки add/remove, оба из которых должны присутствовать. Такое объявление часто используется для создания своего механизма событий с сохранением удобств языка C# в работе с ними.
Например, одна из типичных реализаций заключается в отдельном хранении словаря делегатов событий, в котором присутствуют только те делегаты, на события которых была осуществлена подписка. Доступ к словарю осуществляется по ключам, которыми обычно являются статические поля типа object, используемые только для сравнения их ссылок. Это делается для того, чтобы уменьшить количество памяти, занимаемое экземпляром класса (в случае, если он содержит большое количество нестатических событий). Эта реализация применяется в WinForms.
Как происходит подписка на событие и его вызов?
Модификаторы событий
Для событий могут использоваться модификаторы области видимости (public, protected, private, internal), они могут быть перекрыты (virtual, override, sealed) или не реализованы (abstract, extern). Событие может перекрывать событие с таким же именем из базового класса (new) или быть членом класса (static). Если событие объявлено и с модификатором override и с модификатором abstract одновременно, то наследники класса должны будут переопределить его (равно как и методы или свойства с этими двумя модификаторами).
Какие типы событий бывают?
Как уже было отмечено, тип события всегда должен быть типом делегата. Стандартными типами для событий являются типы EventHandler и EventHandler где TEventArgs — наследник EventArgs. Тип EventHandler используется когда аргументов события не предусмотрено, а тип EventHandler — когда аргументы события есть, тогда для них создается отдельный класс — наследник от EventArgs. Также можно использовать любые другие типы делегатов, но применение типизированного EventHandler выглядит более логичным и красивым.
Как все обстоит в C# 3?
Реализация field-like события, которая описана выше, соответствует языку C# 4 (.NET 4.0). Для более ранних версий существуют весьма существенные отличия.
Неявная реализация использует lock(this) для обеспечения потокобезопасности вместо Interlocked.CompareExchange с циклом. Для статических событий используется lock(typeof(Class)). Вот код, аналогичный раскрытому компилятором неявному определению события в C# 3:
Помимо изменений в работе на разных версиях языка есть еще несколько особенностей.
Особенность №1 — продление времени жизни подписчика
При подписке на событие мы добавляем в список вызовов делегата события ссылку на метод, который будет вызван при вызове события. Таким образом, память, занимаемая объектом, подписавшимся на событие, не будет освобождена до его отписки от события или до уничтожения объекта, заключающего в себе событие. Эта особенность является одной из часто встречаемых причин утечек памяти в приложениях.
Для исправления этого недостатка часто используются weak events, слабые события. Эта тема уже была освещена на Хабре.
Особенность №2 — явная реализация интерфейса
Событие, являющееся частью интерфейса, не может быть реализовано как поле при явной реализации этого интерфейса. В таких случаях следует либо скопировать стандартную реализацию события для реализации как свойство, либо реализовывать эту часть интерфейса неявно. Также, если вам не нужна потокобезопасность этого события, можно использовать самое простое и эффективное определение:
Особенность №3 — безопасный вызов
События перед вызовом следует проверять на null, что следует из описанной выше работы делегатов. От этого разрастается код, для избежания чего существует как минимум два способа. Первый способ описан Джоном Скитом (Jon Skeet) в его книге C# in depth:
Коротко и лаконично. Мы инициализируем делегат события пустым методом, поэтому он никогда не будет null. Вычесть из делегата этот метод невозможно, т.к. он определен при инициализации делегата и у него нет ни имени, ни ссылки на него из любого места программы.
Таким образом, мы можем вызывать события как Changed.SafeRaise(this, EventArgs.Empty), что экономит нам строчки кода. Также можно определить третий вариант метода расширений для случая, когда у нас EventArgs.Empty, чтобы не передавать их явно. Тогда код сократится до Changed.SafeRaise(this), но я не буду рекомендовать такой подход, т.к. для других членов вашей команды это может быть не так явно, как передача пустого аргумента.
Тонкость №4 — что не так со стандартной реализацией?
Бонус: попытка Microsoft сделать контравариантные события
В первой бете C# 4 Microsoft попытались добавить контравариантности событиям. Это позволяло подписываться на событие EventHandler методами, имеющими сигнатуру EventHandler и все работало до тех пор, пока в делегат события не добавлялось несколько методов с разной (но подходящей) сигнатурой. Такой код компилировался, но падал с ошибкой времени выполнения. По всей видимости, обойти это так и не смогли и в релизе C# 4 контравариантность для EventHandler была отключена.
Это не так заметно, если опускать явное создание делегата при подписке, например следующий код отлично скомпилируется:
Это происходит потому, что компилятор сам подставит new EventHandler (. ) к обеим подпискам. Если же хотя бы в одном из мест использовать new EventHandler (. ), то компилятор сообщит об ошибке — невозможно сконвертировать тип EventHandler в EventHandler (здесь Events — пространство имен моего тестового проекта).
Как пользоваться object sender?
Помощь в написании контрольных, курсовых и дипломных работ здесь.
Как программно вызвать событие «AfterCheck (object sender, TreeViewEventArgs e)» для Treview?
Как программно вызвать событие «AfterCheck (object sender, TreeViewEventArgs e)» для Treview? Что.
Object sender вытащить информацию
Добрый день, нужна информация из object sender так как данные передаются между библиотеками.
Работа с (object sender, EventArgs e)
Добрый день. Помогите разобраться. Я объединил 9 лэйблов и создал для них событие Click, назвал его.
Как правильно использовать sender
Такая ситуация. Я в коде создаю некоторое количество обьектов Panel, а в одном Panel по 2 обьекта.
Решение
Добавлено через 2 минуты
Для твоего случая реализация такая
Object sender
Добрый день, такой вопрос. При создании функции(события) в параметры этой функции передается Object.
Sender object для Control.Paint
Доброго времени суток! Нужна ваша помощь. Существует метод private void Plane_Paint(object.
Аргументы object sender и EventArgs e в функциях
Здравствуйте, уважаемые форумчане) Нужно очень детально прокоментировать код к курсачу, а что это.
Обработка и инициация событий
События
Событие — это сообщение, посланное объектом, чтобы сообщить о совершении действия. Это действие может быть вызвано пользовательским взаимодействием, например нажатием кнопки, или какой-то другой программной логикой, например изменением значения свойства. Объект, вызывающий событие, называется отправителем событий. Отправителю событий не известен объект или метод, который будет получать (обрабатывать) созданные им события. Обычно событие является членом отправителя событий; например, событие Click — член класса Button, а событие PropertyChanged — член класса, реализующего интерфейс INotifyPropertyChanged.
Чтобы определить событие, необходимо использовать ключевое слово event в C# или Event в Visual Basic в сигнатуре класса события и задать тип делегата для события. Делегаты описаны в следующем разделе.
Делегаты
Делегат — это тип, содержащий ссылку на метод. Делегат объявляется с сигнатурой, указывающей тип возвращаемого значения и параметры для методов, на которые он ссылается, и может содержать ссылки только на методы, соответствующие его сигнатуре. Таким образом, делегат эквивалентен указателю на строго типизированную функцию или обратному вызову. Объявления делегата достаточно для определения класса делегата.
.NET предоставляет делегаты EventHandler и EventHandler для поддержки большинства сценариев событий. Используйте делегат EventHandler для всех событий, не содержащих данных. Используйте делегат EventHandler для событий, содержащих данные о событии. У этих делегатов нет типа возвращаемого значения. Они принимают два параметра (объект для источника события и объект для данных события).
Эти делегаты являются многоадресными, то есть в них могут храниться ссылки на несколько методов обработки событий. Дополнительные сведения см. на справочной странице класса Delegate. Делегаты позволяют гибко и точно управлять обработкой событий. Делегат выступает как диспетчер событий для класса, вызывающий событие за счет ведения списка зарегистрированных обработчиков для события.
Данные событий
Класс EventArgs является базовым типом для всех классов данных событий. Класс EventArgs используется также, если событие не содержит связанных данных. При создании события, которое лишь уведомляет другие классы о том, что что-то произошло, и не передает никаких данных, используйте класс EventArgs в качестве второго параметра в делегате. Если данные не предоставляются, можно передать значение EventArgs.Empty. Делегат EventHandler содержит класс EventArgs в качестве параметра.
Обработчики событий
Для обработки события в приемнике события необходимо определить метод обработчика события. Этот метод должен соответствовать сигнатуре делегата обрабатываемого события. В обработчике событий выполняются действия, необходимые при возникновении события, например сбор данных, введенных пользователем при нажатии кнопки. Чтобы получать уведомления при возникновении события, метод обработчика события должен быть подписан на событие.
Обработчики статических и динамических событий
.NET позволяет подписчикам регистрироваться для получения уведомлений о событиях как статически, так и динамически. Обработчики статических событий действуют в течение всего жизненного цикла класса, события которого они обрабатывают. Обработчики динамических событий активируются и деактивируются во время выполнения программы, обычно в ответ на определенную условную логику программы. Например, они могут использоваться, если уведомления о событиях требуются только в определенных условиях, либо приложение предоставляет несколько обработчиков событий и выбор конкретного обработчика зависит от условий среды выполнения. В примере в предыдущем разделе показано, как динамически добавлять обработчик события. Дополнительные сведения см. в разделах события (в Visual Basic) и события (в C#).
Создание нескольких событий
Свойства событий состоят из объявлений событий и методов доступа к событиям. Методы доступа к событиям — это определяемые пользователем методы, добавляющие или удаляющие экземпляры делегата события из структуры данных хранения. Обратите внимание, что использование свойств события снижает быстродействие по сравнению с полями события, поскольку перед вызовом каждого делегата события его необходимо извлечь. Необходимо найти компромисс между памятью и скоростью. Если ваш класс определяет много событий, которые вызываются нечасто, необходимо реализовать свойства событий. Дополнительные сведения см. в разделе Практическое руководство. Обработка нескольких событий с помощью их свойств.
События и делегаты
В Заметке о консольных и оконных (Windows Forms) приложениях мы отметили существенную разницу между ними. Консольное приложение реализует концепцию императивного (процедурного) программирования, а управление Windows-приложением основано на понятии события (event). События могут создаваться как пользователем, так и возникать в процессе выполнения приложения. Начнем с простых вещей.
Создадим оконное приложение и запустим его на выполнение. С пустой формой мы можем выполнить только несколько стандартных действий: изменить размер, свернуть, свернуть в окно/развернуть и закрыть приложение.
Для изменения размеров формы подведем указатель мыши (1 событие) к любой ее границе (указатель изменит свою форму), перетянем ее в нужном направлении (2 событие) и отпустим кнопку (3 событие). Последние три действия с формой выполняются после клика мышью (событие 4) на кнопках формы.
Ясно, что такое приложение нам не слишком интересно, тем не менее, очевидна связь между событиями и действиями.
Перенесем с Панели элементов на форму объект «Кнопка» (по умолчанию – button1 класса Button). На вкладке «Конструктор» кнопка видна, на вкладке «Код» о ней нет никакой информации. Однако раскрыв файл Form1.Designer.cs, мы увидим в описании класса Form1 поле:
private System.Windows.Forms.Button button1;
которое задает этот объект, а в методе private void InitializeComponent() обнаружим описание его свойств (имя, местоположение, размер, надпись и т.п.).
Запустим программу снова на выполнение. Нажатие на кнопку (событие) не влечет за собой никаких действий (кроме того, что между нажатием и отпусканием кнопки она подсвечивается).
Смотрим книгу «для чайников». В ней написано: чтобы связать это событие с каким-либо действием необходимо всего лишь выполнить двойной клик на кнопке, в окне кода появится заготовка для метода – обработчика события Click:
private void button1_Click(object sender, EventArgs e)
<
…
>
Увеличим ширину кнопки примерно в три раза. Вставим в тело метода между фигурными скобками оператор:
button1.Text = DateTime.Now.ToString();
Теперь при нажатии кнопки непосредственно на ней мы можем прочитать текущие дату и время нажатия на кнопку.
«Выдающийся» результат! Есть событие, есть реакция на него (обработка события). Как Вам такая автоматизация программирования!
Заметим, что в панели Свойства для объекта button1 на закладке События (щелчок на «желтой молнии») напротив события Click появился метод button1_Click. В окне кода добавили всего один метод с одним оператором в его теле. Что же еще изменилось? Посмотрим содержимое файла Form1.Designer.cs. В нем добавилась загадочная строка:
this.button1.Click += new System.EventHandler(this.button1_Click);
Расшифруем ее. Ключевое слово this – это ссылка на текущий объект Form1 (забавно, что имя объекта совпадает с именем класса). Объект button1 размещен на форме Form1. А Click – очевидно это событие, клик на кнопке. EventHandler – делегат (delegate), представляет метод, который будет обрабатывать событие, не имеющее данных (объявлен в библиотеке System). Тип события обязательно должен совпадать с типом делегата. В скобках указывается имя этого метода button1_Click.
Переведем смысл оператора на русский язык:
Объект.Событие += new Делегат(Метод_обработки);
Символ + определяет подписку обработчика события.
Очевидный вывод: Подписка на событие с использованием делегата приводит к вызову метода при возникновении события.
Возможен ли разрыв связи между событием и методом его обработки? И нет ли у вас ощущения статичности таких связей? Можно ли то же самое достичь программным путем?
Заметим, что этот файл Form1.Designer.cs является текстовым описанием формы и размещенных на ней элементов после запуска программы, что позволяет отобразить ее в режиме конструктора.
Далее многое можно изменять программным путем.
Итак, событие – это сообщение другим объектам программы, что произошло какое-то действие. Действие может быть инициировано пользователем (нажатие клавиши) или же в результате выполнения какого-то фрагмента программы (по условию).
Объект, который вызывает событие, называется отправителем (sender) сообщения, а объект, который сообщение получает – получателем. Роль «почтальона» выполняет делегат. Получатель сообщения имеет метод, который автоматически выполняется в ответ на исходное событие. В нашем примере отправителем и получателем сообщения является объект button1 («makes himself»).
Событием в языке C# называется сущность, предоставляющая две возможности: сообщать об изменениях, а для его пользователей — реагировать на них. В объявлениях классов визуальных компонентов мы найдем большое количество событий, которые могут быть вам полезны. Подсчитайте, сколько событий связано с формой? У меня получилось – 76. А для кнопки – 58, не мало? Если же вам необходимо создать собственное событие, то вы можете его просто объявить:
public event EventHandler myEvent;
Рассмотрим, из чего состоит объявление. Сначала идут модификаторы события, затем ключевое слово event, после него — тип события, который обязательно должен быть типом-делегатом, и идентификатор события, то есть его имя myEvent. Ключевое слово event сообщает компилятору о том, что это не публичное поле, а специальным образом раскрывающаяся конструкция, скрывающая от программиста детали реализации механизма событий (пока это замечание пропустите).
void обработчик(object отправитель, EventArgs е)/…>
Пример использования обобщенного делегата EventHandler
Обобщенный делегат EventHandler используется для
объявления события Ez:
public event EventHandler Ez;
Аргументы, передаваемые в метод, задаются в классе MyEA, который наследуется от класса EventArgs.
Постановка задачи «Управление размерами и цветом формы»
Набор цветов: Red, Green, Blue, Yellow + исходный (добавляйте любые!)
Размеры: 500х150, 550×200, 600×250, 650×300
Элементы управления:
Кнопка button1 — Разрешение/Запрет изменение свойств формы
Кнопка button2 — Перекраска формы в желтый цвет без ограничений
Элемент comboBox1 — для выбора цвета: Red, Green, Blue, прежний
Метка label1 — подсказка: «Выберите цвет закраски формы» к comboBox1.
Начальная форма может выглядеть так:
Создаются два класса:
1) Класс Моих Событий Аргументы:
2) Мой класс Обработка события:
Далее приводится текст файла Form1.cs с комментариями:
Вид формы после перекраски:
Примеры
Другой пример применения делегатов рассмотрен в посте «Делегаты и методы».
Что означают sender и eventArgs/refer to? Как я могу использовать их (для сценария ниже)?
Я пытаюсь создать пользовательский элемент управления с функцией удаления, и я хочу иметь возможность удалить элемент управления, который был нажат на странице, содержащей многие из тех же пользовательских элементов управления.
5 ответов:
отправитель-это элемент управления, для которого выполняется действие (скажем, OnClick, это кнопка).
EventArgs-это аргументы, которые могут оказаться полезными для реализации этого события. С OnClick он не содержит ничего хорошего, но в некоторых случаях, например, в GridView ‘SelectedIndexChanged’, он будет содержать новый индекс или некоторые другие полезные данные.
Крис говорит, что вы можете сделать это:
sender относится к объекту, который вызвал событие, которое запустило обработчик событий. Это полезно, если у вас есть много объектов, использующих один и тот же обработчик событий.
EventArgs является чем-то вроде фиктивного базового класса. Само по себе это более или менее бесполезно, но если вы из него вытекают, вы можете добавить любые данные, которые передаются в обработчики событий.
когда вы реализуете свои собственные события, использовать EventHandler или EventHandler как их тип. Это гарантирует, что вы будете иметь именно эти два параметра для всех ваших событий (что хорошо).
вручную приведите отправителя к типу вашего пользовательского элемента управления, а затем используйте его для удаления или отключения и т. д. Например, что-то вроде этого:
args события подкласс для более сложных элементов управления, например treeview, так что вы можете узнать больше деталей о событии, например, где именно они нажали.
‘sender’ называется объектом, который имеет некоторое действие выполнить на некоторых контроль
‘событие’ имеет некоторую информацию о контроле, который имеет некоторые бихевиористы и личности выполняют каким-то пользователем.когда действие будет создать на происходящие события добавить это держать в пределах массива называется событием АГРС