Студопедия

КАТЕГОРИИ:

АстрономияБиологияГеографияДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРиторикаСоциологияСпортСтроительствоТехнологияФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника


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




Теперь, когда мы разобрались в конструкции и принципе работы метода Counter, посмотрим, как используют делегаты для вызова статических методов. Мы разберем метод StaticDelegateDemo из предыдущего примера.

Сначала StaticDelegateDemo вызывает метод Counter, которому в качестве третьего параметра, соответствующего параметру fb метода Counter, передается null. Поскольку в этом примере параметр fb содержит null, при обработке всех элементов обратного вызова не происходит.

При втором вызове Counter новому объекту делегата Feedback передается другое значение в третьем параметре.

Этот объект-делегат служит оболочкой для другого метода, позволяя выполнять обратный вызов последнего косвенно, через оболочку. Конструктору типа Feedback передается имя статического метода (в этом примере — ProgramFeedbackToConsole), указывающее метод, для которого требуется создать оболочку. Ссылка, которую возвращает оператор new, передается методу Counter.

Теперь, при обработке каждого из элементов набора, метод Counter может вызвать статический метод FeedbackToConsole, определенный в типе Program. Метод FeedbackToConsole просто выводит в консоль строку, указывающую обрабатываемый элемент и его значение.

 

Метод FeedbackToConsole определен внутри типа Program как закрытый, однако метод Counter способен вызывать закрытый метод типа Program. Здесь не возникает проблем с безопасностью, так как Counter и FeedbackToConsole определены в одном типе. Но код будет работать без проблем, даже если Counter определен в другом типе. Короче говоря, не возникает никаких проблем с безопасностью или уровнем доступа, если код одного типа вызывает закрытый член другого типа через делегат при условии, что объект-делегат создан кодом, у которого есть нужные разрешения и доступ.

 

Третий и второй вызовы Counter в методе StaticDelegateDemo отличаются лишь тем, что объект делегата Feedback является оболочкой для другого статического метода — ProgramFeedbackToMsgBox. Метод FeedbackToMsgBox создает строку, указывающую обрабатываемый элемент, которая затем выводится в окне с сообщением.

Ничто в этом примере не нарушает безопасности типов. Например, при создании объекта делегата Feedback компилятор гарантирует, что прототипы методов FeedbackToConsole и FeedbackToMsgBox типа Program не будут отличаться от заданного делегатом Feedback, то есть оба метода будут принимать один параметр (типа Ш32) и возвращать значения одного и того же типа (void). Но что, если у метода FeedbackToConsole был бы такой прототип:

private static Boolean FeedbackToConsole(String value) { }

Компилятор C# откажется компилировать такой код и вернет сообщение об ошибке: «еггог CS0123: The signature of method 'FeedbackToConsole' does not match this delegate type» («ошибка CS0123: Сигнатура метода 'FeedbackToConsole' не соответствует типу этого делегата»).

И С#, и CLR поддерживают прямую и обратную ковариацию ссылочных типов при привязке метода к делегату. Ковариация (covariance) подразумевает, что метод может возвратить тип, производный от типа, возвращаемого делегатом. Обратная ковариация (contra-variance) означает, что метод может принимать параметр, который является базовым для типа параметра делегата. Например, если делегат определить так:

delegate Object MyCallback(FileStream s);

можно создать экземпляр этого делегата, связанный с методом, прототип которого выглядит примерно так:

String SomeMethod(Stream s);

Здесь тип значения, возвращаемого методом SomeMethod (то есть String), является типом, производным от типа, возвращаемого делегатом (Object); такая ковариация разрешена. Тип параметра метода SomeMethod (то есть Stream) — это тип, являющийся базовым классом для типа параметра делегата (FileStream); такая обратная ковариация разрешена.

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

Int32 SomeOtherMethod(Stream s);

Хотя тип значения, возвращаемого SomeOtherMethod, (то есть Int32) является производным от типа значения, возвращаемого методом MyCallback (то есть Object); такая форма ковариации не разрешена, потому что Int32 — значимый тип. Значимые типы и void не могут использоваться для прямой и обратной ковариации, потому что их структура памяти изменяется, тогда как структура памяти ссылочных типов — всегда указатель. К счастью, компилятор С# возвращает ошибку при попытке выполнить неразрешенную операцию.


Поделиться:

Дата добавления: 2015-04-21; просмотров: 132; Мы поможем в написании вашей работы!; Нарушение авторских прав





lektsii.com - Лекции.Ком - 2014-2024 год. (0.005 сек.) Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав
Главная страница Случайная страница Контакты