Пример использования делегатов. Функции высших порядков

Для того чтобы воспользоваться делегатом, необходимо создать его экземпляр и задать имена методов, на которые он будет ссылаться. При вызове экземпляра делегата вызываются все заданные в нем методы.

using System:

namespace ConsoleApplicationi

delegate void Del ( ref string s ); // объявление делегата

class Class

{

public static void C001 ( ref string s ) // метод 1

string temp = " " ;

for ( int i = 0: i < s.Length: ++i )

if ( s [ i ] == '0' || s [ i ]== ' 0 ' ) temp += '0';

else if ( s [ i ] == ' I ' ) temp += ' 1' ;

else temp += s [ i j ;

}

s = temp;

}

public static void Hack ( ref string s ) // метод 2

{

string temp = " " ;

for ( int i = 0; i < s.Length; ++i )

if ( i / 2 * 2 == i ) temp += char.ToUpper( s [ i ] );

else temp += s [ i ] ;

}

s = temp;

static void Main{

string s = "cool hackers";

Del d; // экземпляр делегата

for ( int i = 0; i < 2; ++i )

{ d = new Del( COOl ); // инициализация методом 1

if ( i == 1 ) d = new Del(Hack); // инициализация методом 2

d( ref s ); // использование делегата для вызова методов

Console.WriteLine( s );

} }

Случаи использования делегатов.

Делегаты применяются в основном для следующих целей:

• получения возможности определять вызываемый метод не при компиляции, а динамически во время выполнения программы;

• обеспечения связи между объектами по типу «источник — наблюдатель»;

• создания универсальных методов, в которые можно передавать другие методы;

• поддержки механизма обратных вызовов. Все эти варианты подробно обсуждаются далее. Рассмотрим сначала пример реализации первой из этих целей. В листинге 10.1 объявляется делегат, с помощью которого один и тот же оператор используется для вызова двух разных методов.

Использование делегата имеет тот же синтаксис, что и вызов метода. Если делегат хранит ссылки на несколько методов, они вызываются последовательно в том орядке, в котором были добавлены в делегат.

Добавление метода в список выполняется либо с помощью метода Combine, унаследованного от класса System.Delegate, либо, что удобнее, с помощью перегруженной операции сложения.

Управление памятью. Генерация объектов

Сборка мусора

При освобождении памяти строится дерево живых объектов. Построение начинается с корневых объектов (application roots) – это глобальные и статические объекты. Зацикливания избегают с помощью проверки на принадлежность очередного объекта графу.

Затем сборщик мусора начинает искать фрагменты, не вошедшие в дерево. Как только такие фрагменты найдены, путем копирования памяти используемые фрагменты приводятся в более компактный вид (сдвигаются вниз). После этого происходит обновление ссылок на объекты в куче. Память приводится в компактный вид только в том случае, если сборщик мусора обнаружил значительно количество недоступных объектов. С целью оптимизации большие фрагменты памяти не перемещаются.

Для оптимизации процесса сборки мусора введено понятие о трех поколениях объектов:

Все объекты создаются в поколении 0 (generation 0). Объекты, пережившие сборку мусора, переходят в следующее поколение: 1 или 2.

При запуске сборщик мусора сначала ищет недостижимые объекты в поколении 0. Если они найдены, память приводится к компактному виду, а объекты пережившие сборку мусора переходят в поколение 0. Просмотр объектов поколении 1 будет происходить только в том случае, если памяти, освобожденной от объектов поколения 0 окажется недостаточно для размещения новых объектов. Объекты из поколения 1, пережившие сборку мусора переходят в поколение 2. Просмотр объектов поколения 2 происходит, если просмотр объектов поколений 0 и 1 не освободил достаточного количества памяти

Интерфейс IDisposable.

Выше уже упоминалось о том, что метод Finalize не обеспечивает надежного освобождения ресурсов, не находящихся под управлением сборщика мусора. В программировании .NET класс реализует интерфейс IDisposable с единственным методом Dispose, освобождающим занятые ресурсы:

Public Interface IDisposable

Sub Dispose()

End Interface

Итак, запомните следующее правило:

Если ваш класс использует другой класс, реализующий IDisposable, то в конце работы с ним необходимо вызвать метод Dispose.

Как будет показано в главе 8, метод Dispose должен вызываться в каждом графическом приложении, зависящем от базового класса Component, поскольку это необходимо для освобождения графических контекстов, используемых всеми компонентами.

Список классов .NET Framework, реализующих интерфейс IDisposabe (следовательно, поддерживающих метод Dispose, который должен вызываться в приложениях), приведен в описании интерфейса IDisposable в электронной документации.

Класс System.GC

Управляет системным сборщиком мусора — службой, которая автоматически высвобождает неиспользуемую память.

Методы этого класса оказывают влияние на то, когда выполняется сборка мусора и когда высвобождаются ресурсы, выделенные объектом.Свойства этого класса предоставляют сведения об общем объеме доступной памяти системы и о том, к какому поколению относится память, выделенная объекту.

Сборщик мусора отслеживает и уничтожает объекты, находящиеся в управляемой памяти.Периодически сборщик выполняет сборку мусора, чтобы высвободить память, отведенную под объекты, на которые нет действительных ссылок.Сборка мусора автоматически запускается в случае, если требуемый объем памяти больше доступного объема свободной памяти.Кроме того, приложение может принудительно запустить сборку мусора с помощью метода Collect.

Сборка мусора состоит из следующих шагов:

А)Сборщик мусора осуществляет поиск управляемых объектов, на которые есть ссылки в управляемом коде.

Б)Сборщик мусора пытается завершить объекты, на которые нет ссылок.

В)Сборщик мусора освобождает объекты, на которые нет ссылок, и высвобождает выделенную им память.

Во время сборки мусора сборщик не освобождает объект, если находит хотя бы одну ссылку на него в управляемом коде.Тем не менее, сборщик мусора не распознает ссылки на объект из неуправляемого кода и потому может уничтожать объекты, которые используются исключительно в неуправляемом коде, если явно не предотвратить такое действие.

Наши рекомендации