Доброго времени суток! Дорогие бородатые программисты, использующие .Net, помогите пожалуйста разобраться с ссылочными и значимыми типами. Суть такова: в данный момент читаю Рихтера - CLR via C#, Глава 11. События. Все прекрасно и очевидно, пока не начинаю вдумываться в детали. А именно - вот фрагмент, выдержка из книги:
Код | //В классе MailManager есть //строчка кода, определяющая сам член-событие: //public event EventHandler<NewMailEventArgs> NewMail; //При компиляции этой строки компилятор превращает ее в следующие три //конструкции: // 1. ЗАКРЫТОЕ поле делегата, инициализированное значением null private EventHandler<NewMailEventArgs> NewMail = null; // 2. ОТКРЫТЫЙ метод add_Xxx (где Xxx – это имя события) // Позволяет объектам регистрироваться для получения уведомлений о событии public void add_NewMail(EventHandler<NewMailEventArgs> value) { // Цикл и вызов CompareExchange – хитроумный способ добавления // делегата способом, безопасным в отношении потоков EventHandler<NewMailEventArgs>prevHandler; EventHandler<NewMailEventArgs> newMail = this.NewMail; do { prevHandler = newMail; EventHandler<NewMailEventArgs> newHandler = (EventHandler<NewMailEventArgs>) Delegate.Combine(prevHandler, value); newMail = Interlocked.CompareExchange<EventHandler<NewMailEventArgs>>( ref this.NewMail, newHandler, prevHandler); } while (newMail != prevHandler); } // 3. ОТКРЫТЫЙ метод remove_Xxx (где Xxx – это имя события) // Позволяет объектам отменять регистрацию в качестве // получателей уведомлений о cобытии public void remove_NewMail(EventHandler<NewMailEventArgs> value) { // Цикл и вызов CompareExchange – хитроумный способ // удаления делегата способом, безопасным в отношении потоков EventHandler<NewMailEventArgs> prevHandler; EventHandler<NewMailEventArgs> newMail = this.NewMail; do { prevHandler = newMail; EventHandler<NewMailEventArgs> newHandler = (EventHandler<NewMailEventArgs>) Delegate.Remove(prevHandler, value); newMail = Interlocked.CompareExchange<EventHandler<NewMailEventArgs>>( ref this.NewMail, newHandler, prevHandler); } while (newMail != prevHandler); }
|
Логика мне ясна. Не понятно одно - делегаты это ссылочные типы. Значит переменная - содержит ссылку на объект в куче. Верно? Верно. И, к примеру вот этот момент мне не дает покоя:
Код | EventHandler<NewMailEventArgs> prevHandler; EventHandler<NewMailEventArgs> newMail = this.NewMail; do { prevHandler = newMail; EventHandler<NewMailEventArgs> newHandler = (EventHandler<NewMailEventArgs>) Delegate.Remove(prevHandler, value); newMail = Interlocked.CompareExchange<EventHandler<NewMailEventArgs>>( ref this.NewMail, newHandler, prevHandler);
|
Судя по коду: EventHandler<NewMailEventArgs> newMail = this.NewMail; prevHandler = newMail;
prevHandler ссылается на один и тот же объект что и this.NewMail а дальше мы сравниваем по сути один и тот же объект: Interlocked.CompareExchange<EventHandler<NewMailEventArgs>>(ref this.NewMail, newHandler, prevHandler);
Прошу, объясните бестолковому что тут происходит? Мб в делегате оператор implicit перегружен так, что создает новый объект, копирует поля и возвращает ссылку на него? Простите за тупость, еще раз. |