Эндрю Троелсен - ЯЗЫК ПРОГРАММИРОВАНИЯ С# 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-е издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
// Класс Garage хранит список типов Car.
using System.Collections;
…
public class Garage {
// Создание списка всех машин в гараже.
ArrayList theCars = new ArrayList();
// Создание машин в гараже.
public Garage() {
// Напомним, что конструктор был обновлен,
// и теперь можно установить значения isDirty и shouldRotate.
theCars.Add(new Car("Viper", 100, 0, true, false));
theCars.Add(new Car("Fred", 100, 0, false, false));
theCars.Add(new Car("BillyBob", 100, 0, false, true));
}
}
Класс Garage будет определять общедоступный метод ProcessCars(), который в качестве единственного аргумента получит новый тип делегата (Car.CarDelegate). В ProcessCars() каждый объект Car из коллекции будет передаваться в виде параметра "той функции, на которую указывает" делегат. При этом ProcessCars() использует члены Target и Method из System.MulticastDelegate, чтобы определить, на какую из функций делегат указывает в настоящий момент.
// Класс Garage имеет метод, использующий CarDelegate.
using System.Collections;
…
public class Garage {
…
// Этот метод получает Car.CarDelegate в виде параметра.
public void ProcessCars(Car.CarDelegate proc) {
// Куда направить вызов?
Console.WriteLine("***** Вызывается: {0} *****", proc. Method);
// Вызывается метод экземпляра или статический метод?
if (proc. Target!= null) Console.WriteLine("-›Цель: {0} ", proc. Target);
else Console.WriteLine("-›Целевым является статический метод");
// Вызов "указанного" метода всех машин по очереди.
foreach (Car с in theCars) {
Console.WriteLine("\n-› Обработка Car");
proc(c);
}
}
}
Как и в случае любого делегата, при вызове ProcessCars() мы должны указать имя метода, который обработает запрос. Напомним, что такой метод может быть или статическим, или методом экземпляра. Для примера предположим, что в качестве такого метода будут использоваться члены экземпляра нового класса ServiceDepartment (отдел технического обслуживании), которым назначены имела WashCar() и RotateTires(). Обратите внимание на то, что эти два метода используют новые свойства Rotate и Dirty типа Car.
// Этот класс определяет методы, которые будут вызываться
// типом Car.CarDelegate.
public class ServiceDepartment {
public void WashCar(Car c) {
if (c.Dirty) Console.WriteLine("Моем машину");
else Console.WriteLine("Эта машина уже помыта…");
}
public void RotateTires(Car с) {
if (c.Rotate) Console.WriteLine("Меняем шины");
else Console.WriteLine("Менять шины не требуется…");
}
}
Теперь проиллюстрируем взаимодействие между новыми типами Car, CarDelegate, Garage и ServiceDepartment, рассмотрев их использование в следующем фрагменте программного кода.
// Garage направляет все заказы в ServiceDepartment
// (найти хорошего механика всегда проблема…)
public class Program {
static void Main(string[] args) {
// Создание гаража.
Garage g = new Garage();
// Создание отделения обслуживания,
ServiceDepartment sd = new ServiceDepartment();
// Garage моет машины и меняет шины,
// делегируя соответствующие полномочия ServiceDepartment.
g.ProcessCars(new Car.CarDelegate(sd.WashCar));
g.ProcessCars(new Car.CarDelegate(sd.RotateTires));
Console.ReadLine();
}
}
На рис. 8.6 показан соответствующий вывод.

Рис. 8.6. Перекладывание ответственности
Анализ программного кода делегирования
Предложенный выше метод Main() начинается с создания экземпляров типов Garage и ServiceDepartment. Когда вы пишете
// Помыть все грязные машины.
g.ProcessCars(new Car.CarDelegate(sd.WashCar));
это на самом деле означает: "Добавить указатель на метод ServiceDepartment.WashCar() к объекту Car.CarDelegate и передать этот объект в Garage.ProcessCars()". Подобно любому автомобильному предприятию в реальном мире, все заказы передаются в отдел технического обслуживания (что и объясняет, почему замена масла, обычно требующая 30 минут, занимает целых 2 часа). С учетом этого ProcessCars() можно интерпретировать так.
// CarDelegate указывает на функцию ServiceDepartment.WashCar.
public void ProсessCars(Car.CarDelegate proc) {
foreach (Car с in theCars)
proc(c); // proc(c) =› ServiceDepartment.WashCar(c)
…
}
Точно так же, если вы говорите
// Поменять шины.
g.ProcessCars(new Car.CarDelegate(sd.RotateTires));
то ProcessCars() можно интерпретировать, как
// CarDelegate указывает на функцию ServiceDepartment.RotateTires.
public void ProcessCars(Car.CarDelegate proc) {
…
foreach(Car с in the Cars)
proc(c); //proc(c) =› ServiceDepartment.RotateTires(e)
…
}
Исходный код. Проект CarGarage размещен в подкаталоге, соответствующем главе 8.
Ковариантность делегатов
К этому моменту вы должны чувствовать себя более уверенно при создании и использовании типов делегата. Перед тем как перейти к изучению синтаксиса событий в C#, мы рассмотрим новую возможность .NET 2.0, связанную с делегатами и обозначенную термином ковариантность. Вы могли обратить внимание на то, что все делегаты, созданные нами до сих пор, указывали на методы, возвращающие простые числовые типы данных (или не возвращающие значений вообще). Но предположим, что нам нужен делегат, способный указывать на методы, возвращающие пользовательский тип класса.
// Определение делегата, который позволит указывать на объекты,
// возвращающие типы Car.
public delegate Car ObtainCarDelegate();
Мы можем определить целевой объект для делегата так, как обычно.
class Program {
public delegate Car ObtainCarDelegate();
public static Car GetBasicCar() {return new Car();}
static void Main(string[] args) {
ObtainCarDelegate targetA = new ObtainCarDelegate(GetBasicCar);
Car c = targetA();
Console.ReadLine();
}
}
Пока что все выглядит прекрасно. Но что делать, если мы получим новый класс SportsCar из типа Car и потребуется делегат, который сможет указывать на методы, возвращаемые этим новым типом класса? До появления .NET 2.0 в таком случае вам пришлось бы определить новый делегат.
// Новый делегат, указывающий на целевые объекты,
// возвращающие типы SportsCar.
public delegate SportsCar ObtainSportsCarDelegate();
У нас теперь два типа делегата, и мы должны создать по экземпляру каждого из них, чтобы получить типы Car и SportsCar.
class Program {
public delegate CarObtainCarDelegate();
public delegate SportsCarObtainSportsCarDelegate();
public static CarGetBasicCar() {return new Car();}
public static SportsCarGetSportsCar() {return new SportsCar();}
Интервал:
Закладка: