Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > .NET для новичков > Ссылочные VS значимые поля


Автор: lllJollyRogerlll 27.7.2017, 21:25
Доброго времени суток!
Дорогие бородатые программисты, использующие .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);  smile 

Прошу, объясните бестолковому что тут происходит? 
Мб в делегате оператор implicit перегружен так, что создает новый объект, копирует поля и возвращает ссылку на него?
Простите за тупость, еще раз.   smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)