Главная страница Случайная страница КАТЕГОРИИ: АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Делегаты и анонимные методы
Хороший стиль программирования требует, чтобы локальная переменная объявлялась как можно ближе к точке ее непосредственного использования. Анонимные методы позволяют сделать то же самое для методов, т.к. описание обычных функций отделено от их использования. Когда объект объявляется непосредственно в точке, где он используется, то это делает код более понятным, облегчает его сопровождение, что крайне важно для долгоживущих проектов. Эти средства позволяют уменьшить расстояние между объявлением объекта и его использованием. Метод, на который ссылается делегат, нередко используется только для этой цели. Иными словами, единственным основанием для существования метода служит то обстоятельство, что он может быть вызван посредством делегата, но сам он не вызывается вообще. В подобных случаях можно воспользоваться анонимной функцией, чтобы не создавать отдельный метод. Анонимная функция, по существу, представляет собой безымянный кодовый блок, передаваемый конструктору делегата. Преимущество анонимной функции состоит, в частности, в ее простоте. Благодаря ей отпадает необходимость объявлять отдельный метод, единственное назначение которого состоит в том, что он передается делегату. Анонимная функция лишена имени, для нее не указан тип, как подобает приличным объектам языка. Во многом анонимные методы напоминают константы, заданные литералами, которые также заданы своими значениями и тип которых определяется по самому значению. Описание анонимного метода является выражением и может встречаться всюду, где разрешены выражения, - в правой части оператора присваивания в качестве фактического аргумента при вызове метода. Синтаксис описания метода-выражения следующий: delegate [(< сигнатура метода>)] < тело метода>Сигнатура метода может отсутствовать, если у метода нет входных и выходных аргументов. Тело метода - обычный блок. У анонимного метода нет внутреннего, присущего ему функционального типа. Но для корректного применения анонимного метода его тип должен приводиться к типу делегата, заданного контекстом использования анонимного метода. Поскольку выражение, задающее анонимный метод, может появляться в правой части оператора присваивания или в качестве фактического аргумента, должно выполняться соответствие по типу анонимного метода с левой частью оператора присваивания или с формальным аргументом вызываемого метода, тип которых задается некоторым делегатом. В описание анонимного метода не входит описание возвращаемого методом значения. Компилятор сам определяет, как реализован метод, анализируя его явное описание. Если в описании анонимного метода присутствуют один или несколько операторов return, сопровождаемых возвращаемым значением, то анонимный метод реализован как функция и тип возвращаемого значения определяется типом возвращаемых значений в операторах return. Понятно, что все возвращаемые значения должны быть согласованы по типу, иначе возникнет ошибка периода компиляции. Если операторов return в теле метода нет или они не возвращают значение, то метод реализован как процедура, возвращающая void в качестве результата. Так компилятор может установить соответствие между возвращаемым типом источника и цели. Когда для анонимного метода не задана сигнатура, то применяется следующее правило установления соответствия типов источника и цели. Анонимный метод соответствует по типу любому делегату с произвольным числом аргументов, если только ни один из аргументов не сопровождается описателями ref или out. Если же функциональный тип формального аргумента или левой части оператора присваивания содержит входные или обновляемые аргументы, то соответствия нет, и это приводит к ошибке периода компиляции. Когда для анонимного метода задана сигнатура, применятся следующее правило установления соответствия: сигнатуры источника и цели должны совпадать. Заметьте, речь идет о строгом совпадении типов. Не допускается, чтобы тип цели был double, а у источника – int. class Father { } class Son: Father { } delegate string D1(string s, double x); delegate void D2(string s, out string s1); delegate string D3(Father item); public void TestAnonymToDelegate() { D1 d1 = delegate {return " OK! "; }; D1 d12 = delegate(string s, double x) { return s + x; }; Console.WriteLine(d1(" s", 5)); Console.WriteLine(d12(" 12", 3)); string res; D2 d2 = delegate(string s, out string r){r = s+s; }; d2(" Hello ", out res); Console.WriteLine(res); D3 d3 = delegate(Father item) { return item.ToString(); }; Console.WriteLine(d3(new Son())); }К типу делегата D1 приводятся типы двух анонимных методов с разной сигнатурой. Приведение возможно, поскольку оба анонимных метода возвращают строку в качестве результата, что согласуется с типом возвращаемого значения делегата D1. Анонимный метод, используемый для задания переменной d1, не имеет сигнатуры, что позволяет сопоставить его с типом делегата D1, у которого нет выходных аргументов. Сигнатура анонимного метода, используемого для задания переменной d12, полностью совпадает с сигнатурой делегата D1. Анонимный метод, используемый для задания переменной d2, соответствует по типу делегату D2, требующему, чтобы метод был реализован как процедура и имел выходной аргумент с описателем out. Аналогично устанавливается соответствие между анонимным методом переменной d3 и типом делегата D3. Естественно, что при вызове функциональной переменной d3 в качестве фактического аргумента может передаваться объект класса Son, в то время как тип аргумента анонимного метода полностью соответствует типу аргумента делегата D3 и принадлежит родительскому классу Father.
|