Во многих языках, если создано несколько делегатов, которые закрывают некоторые переменные в данной области, каждый делегат, закрывающий любую из этих переменных, будет закрывать все из них.Например:
Action blah(Dictionary<string, int> dict, List<string> list)
{
int i;
list.ForEach( (st) => if (dict.Contains(st)) i++; );
return () => Console.WriteLine("The value was {0}", i);
}
Этот метод создаст двух делегатов.Первым нужны переменные dict
и i
, и они будут отменены до выхода из функции.Второму нужно только i
, но вызывающий может удерживать его бесконечно долго.Пока вызывающая сторона сохраняет делегат, возвращенный этим методом, переданный словарь не будет собираемым.
Компилятор мог бы избежать этой проблемы, создав два замыкания, одно из которых содержалоdict
и int[1]
, а другой из которых только что держал int[1]
;оба замыкания будут содержать ссылку на один и тот же int[1]
, сохраняя тем самым требуемую семантику.На практике, однако, дополнительные расходы связаны с лишними захватами.