Страницы

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

суббота, 27 апреля 2019 г.

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

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), и почему первый вариант удаляет как надо а второй не срабатывает вовсе?


Ответ

Пускай 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:
... Результатом является новый список вызова, состоящий из списка первого операнда с удалёнными элементами списка второго операнда, при условии, что второй список является непрерывным (нетривиальным) подсписком первого [...] В противном случае, результатом является вычитаемое.

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

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