Страницы

Поиск по вопросам

воскресенье, 16 февраля 2020 г.

Групповые делегаты

#c_sharp #делегаты


Action a1 = () => Console.Write(1); 
Action a2 = () => Console.Write(2); 
Action a3 = () => Console.Write(3); 
((a1 + a2 + a3) - (a1 + a2))(); 
((a1 + a2 + a3) - (a1 + a3))();


Увидел данный пример и стало интересно. Как в данном случае отрабатывает удаление
делегата. Что происходит при (a1 + a2) и (a1 + a3), и почему первый вариант удаляет
как надо а второй не срабатывает вовсе?
    


Ответы

Ответ 1



Пускай a1 + a2 + a3 превращается в делегат, который условно обозначим [a1, a2, a3], a1 + a2 -- [a1, a2], a1 + a3 -- [a1, a3]. При вычитании в [a1, a2, a3] ищется кусок подряд, который равен вычитаемому. Для [a1, a2] такой кусок найдётся, начиная с индекса 0, а для [a1, a3] -- нет. Поэтому при вычитании [a1, a2, a3] - [a1, a2] получается [a3], а при вычитании [a1, a2, a3] - [a1, a3] подходящий кусок не находится, и вычитание не происходит. Смысл такого правила в том, что если уж делегат получен сложением одного списка с другими, то это первый список будет найден в суммарном делегате как подсписок. Поэтому вычитание в этом случае имеет смысл. Цитата из стандарта, параграф 7.8.5: ... Результатом является новый список вызова, состоящий из списка первого операнда с удалёнными элементами списка второго операнда, при условии, что второй список является непрерывным (нетривиальным) подсписком первого [...] В противном случае, результатом является вычитаемое.

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

Отправить комментарий