Эндрю Троелсен - ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание
- Название:ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс
- Год:2007
- Город:Москва • Санкт-Петербург • Киев
- ISBN:ISBN 5-8459-1124-9
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Эндрю Троелсен - ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание краткое содержание
В этой книге содержится описание базовых принципов функционирования платформы .NET, системы типов .NET и различных инструментальных средств разработки, используемых при создании приложений .NET. Представлены базовые возможности языка программирования C# 2005, включая новые синтаксические конструкции, появившиеся с выходом .NET 2.0, а также синтаксис и семантика языка CIL. В книге рассматривается формат сборок .NET, библиотеки базовых классов .NET. файловый ввод-вывод, возможности удаленного доступа, конструкция приложений Windows Forms, доступ к базам данных с помощью ADO.NET, создание Web-приложений ASP.NET и Web-служб XML. Книга содержит множество примеров программного кода, призванного помочь читателю в освоении предлагаемого материала. Программный код примеров можно загрузить с Web-сайта издательства.
ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
}
Делегаты могут также "указывать" на методы, содержащие любое число параметров out или ref. В качестве примера рассмотрим следующий тип делегата.
public delegate string MyOtherDelegate (outbool a, refbool b, int c);
Сигнатуры методов Invoke() и BeginInvoke() выглядят так, как и ожидается, но обратите внимание на метод EndInvoke(), который теперь включает и все аргументы out/ref, определенные типом делегата.
sealed class MyOtherDelegate: System.MulticastDelegate {
public MyOtherDelegate(object target, uint functionAddress);
public stringInvoke( outbool a, refbool b, int c);
public IAsyncResult BeginInvoke( outbool a, refbool b, int c, AsyncCallback cb, object state);
public stringEndInvoke (outbool a, refbool b, IAsyncResult result);
}
Итак, в результате определения делегата в C# компилятор генерирует изолированный класс с тремя методами, для которых возвращаемые значения и типы параметров соответствуют декларации делегата. Следующий псевдокод приближенно описывает соответствующий базовый шаблон.
// Это только псевдокод!
public sealed class ИмяДелегата : System.MulticastDelegate {
public ИмяДелегата (object target, uint functionAddress);
public возвращаемоеЗначениеДелегата Invoke( всеПараметрыДелегата );
public IAsyncResult BeginInvoke( всеПараметрыДелегата , AsyncCallback cb, object state);
public возвращаемоеЗначениеДелегата EndInvoke(всеПараметрыRefOutДелегата, IAsyncResult result);
}
Базовые классы System.MulticastDelegate и System.Delegate
Таким образом, при создании типов c помощью) ключевого слова delegate в C# вы неявно объявляете тип класса, являющегося производным от System.MulticastDelegate. Этот класс обеспечивает своим потомкам доступ к списку с адресами тех методов, которые поддерживаются типом делегата, а также предлагает несколько дополнительных методов (и ряд перегруженных операций), обеспечивающих взаимодействие со списком вызовов. Вот программный код некоторых членов System.MulticastDelegate.
[Serializable]
public abstract class MulticastDelegate: Delegate {
// Методы
public sealed override Delegate[] GetInvocationList();
public static bool operator==(MulticastDelegate d1, MulticastDelegate d2);
public static bool operator!=(MulticastDelegate d1, MulticastDelegate d2);
// Поля
private IntPtr _invocationCount;
private object _invocationList;
}
Дополнительные функциональные возможности System.MulticastDelegate получает от своего родительского класса System.Delegate. Вот часть определения этого класса.
[Serializable, ClassInterface(ClassInterfaceType.AutoDual)]
public abstract class Delegate: ICloneable, ISerializable {
// Методы
public static Delegate Combine(params Delegate[] delegates);
public static Delegate Combine(Delegate a, Delegate b);
public static Delegate Remove(Delegate source, Delegate value);
public static Delegate RemoveAll(Delegate source, Delegate value);
// Перегруженные операции
public static bool operator==(Delegate d1, Delegate d2);
public static bool operator!=(Delegate d1, Delegate d2);
// Свойства
public MethodInfo Method {get;}
public object Target {get;}
}
Здесь следует подчеркнуть, что от вас никогда не потребуется непосредственно получать производные этих базовых классов, и вы можете ограничить себя использованием только членов, указанных в табл. 8.1.
Таблица 8.1.Избранные члены System.MulticastDelegate и System.Delegate
Наследуемый член | Описание |
---|---|
Method | Свойство, возвращающее тип System.Reflection.Methodlnfo, который представляет информацию о статическом методе, поддерживаемом делегатом |
Target | Если доступный для вызова метод определен на уровне объекта (а не как статический метод), то Target возвратит имя метода, поддерживаемого делегатом. Если возвращенным значением Target оказывается null, то доступный для вызова метод является статическим |
Combine() | Статический метод, добавляющий метод в список методов, поддерживаемых делегатом. В C# этот метод вызывается с помощью перегруженной операции += |
GetInvocationList() | Метод, возвращающий массив типов System.Delegate, каждый из которых представляет конкретный доступный для вызова метод |
Remove() RemoveAll() | Статические методы, удаляющие метод (или все методы) из списка вызовов. В C# метод Remove() можно вызвать опосредованно, используя перегруженную операцию –= |
Простейший пример делегата
В начале освоения приемов работы с делегатами у программиста может возникать много вопросов. Поэтому мы начнем с рассмотрения очень простого примера, в котором используется созданный нами тип делегата BinaryOp. Вот программный код, который мы собираемся проанализировать.
namespace SimpleDelegate {
// Этот делегат может указывать на любой метод,
// принимавший два целых значения
// и возвращающий целое значение.
public delegate int BinaryOp(int x, int y);
// Этот класс содержит методы, на которые
// будет указывать BinaryOp.
public class SimpleMath {
public static int Add(int x, int y) {return x + y;}
public static int Subtract(int x, int y) {return x – у;}
}
class Program {
static void Main(string[] args) {
Console.WriteLine("***** пример делегата *****\n");
// Создание объекта BinaryOp,
// "указывающего" на SimpleMath.Add().
BinaryOp b = new BinaryOp(SimpleMath.Add);
// Вызов метода Add() с помощью делегата.
Console.WriteLine(''10 + 10 равно {0}", b(10, 10));
Console.ReadLine();
}
}
}
Снова обратите внимание на формат делегата BinaryOp, который может указывать на любой метод, принимающий два целых значения и возвращающий целое значение. Итак, мы создали класс с именем SimpleMath, определяющий два статических метода, которые (как неожиданно) соответствуют шаблону, определенному делегатом BinaryOp.
Чтобы добавить целевой метод в делегат, нужно просто передать имя этою метода конструктору делегата. Тогда вы сможете вызвать указанный член с помощью синтаксической конструкции, подобной прямому вызову функции.
// Здесь на самом деле вызывается Invoke()!
Console.WriteLine("10 + 10 is {0}", b(10, 10));
"За кулисами" среда выполнения вызывает сгенерированный компилятором метод Invoke(). Вы можете проверить это сами, если откроете компоновочный блок с помощью ildasm.exe и посмотрите на программный код CIL метода Main().
.method private hidebysig static void Main(string[] args) cil managed {
…
.locals init ([0] class SimpleDelegate.BinaryOp b)
ldftn int32 SimpleDelegate.SimpleMath::Add(int32, int32)
…
newobj instance void SimpleDelegate.BinaryOp::.ctor(object, native int)
stloc.0
ldstr "10 + 10 is {0}"
ldloc.0
ldc.i4.s 10
ldc.i4.s 10
callvirt instance int32 SimpleDelegate.BinaryOp::Invoke(int32, int32)
…
}
Напомним, что делегаты .NET (в отличие от указателей функций в C) обеспечивают типовую безопасность. Поэтому, если вы попытаетесь передать делегату метод, "не соответствующий шаблону", вы получите сообщение об ошибке компиляции. Например, предположим, что класс SimpleMath определяет еще один метод, носящий имя SquareNumber().
Читать дальшеИнтервал:
Закладка: