Kniga-Online.club
» » » » Герберт Шилдт - C# 4.0: полное руководство

Герберт Шилдт - C# 4.0: полное руководство

Читать бесплатно Герберт Шилдт - C# 4.0: полное руководство. Жанр: Программирование издательство -, год 2004. Так же читаем полные версии (весь текст) онлайн без регистрации и SMS на сайте kniga-online.club или прочесть краткое содержание, предисловие (аннотацию), описание и ознакомиться с отзывами (комментариями) о произведении.
Перейти на страницу:

Ниже приведен пример групповой адресации. Это переработанный вариант предыдущих примеров, в котором тип значений, возвращаемых методами манипулирования строками, изменен на void, а для возврата измененной строки в вызывающую часть кода служит параметр типа ref. Благодаря этому методы оказываются более приспособленными для групповой адресации.

// Продемонстрировать групповую адресацию.

using System;

// Объявить тип делегата.

delegate void StrMod(ref string str);

class MultiCastDemo {

  // Заменить пробелы дефисами.

  static void ReplaceSpaces(ref string s) {

    Console.WriteLine("Замена пробелов дефисами.");

    s = s.Replace(' ' ,    '-');

  }

  // Удалить пробелы.

  static void RemoveSpaces(ref string s) {

    string temp = "";

    int i;

    Console.WriteLine("Удаление пробелов.");

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

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

    s = temp;

  }

  // Обратить строку.

  static void Reverse(ref string s) {

    string temp = "";

    int i, j;

    Console.WriteLine("Обращение строки.");

    for(j=0, i=s.Length-1; i >= 0; i—, j++) temp += s[i];

    s = temp;

  }

  static void Main() {

    // Сконструировать делегаты.

    StrMod strOp;

    StrMod replaceSp = ReplaceSpaces;

    StrMod removeSp = RemoveSpaces;

    StrMod reverseStr = Reverse;

    string str = "Это простой тест.";

    // Организовать групповую адресацию.

    strOp = replaceSp;

    strOp += reverseStr;

    // Обратиться к делегату с групповой адресацией.

    strOp(ref str);

    Console.WriteLine("Результирующая строка: " + str);

    Console.WriteLine();

    // Удалить метод замены пробелов и добавить метод удаления пробелов.

    strOp -= replaceSp;

    strOp += removeSp;

    str = "Это простой тест."; // восстановить исходную строку

    // Обратиться к делегату с групповой адресацией.

    strOp(ref str);

    Console.WriteLine("Результирующая строка: " + str);

    Console.WriteLine() ;

  }

}

Выполнение этого кода приводит к следующему результату.

Замена пробелов дефисами.

Обращение строки.

Результирующая строка:    .тсет-йотсорп-отЭ

Обращение строки.

Удаление пробелов.

Результирующая строка:    .тсетйотсорпотЭ

В методе Main() из рассматриваемого здесь примера кода создаются четыре экземпляра делегата. Первый из них, strOp, является пустым, а три остальных ссылаются на конкретные методы видоизменения строки. Затем организуется групповая адресация для вызова методов RemoveSpaces() и Reverse(). Это делается в приведенных ниже строках кода.

strOp = replaceSp;

strOp += reverseStr

Сначала делегату strOp присваивается ссылка replaceSp, а затем с помощью оператора += добавляется ссылка reverseStr. При обращении к делегату strOp вызываются оба метода, заменяя пробелы дефисами и обращая строку, как и показывает приведенный выше результат.

Далее ссылка replaceSp удаляется из цепочки вызовов в следующей строке кода:

strOp -= replaceSp;

и добавляется ссылка removeSp в строке кода.

strOp += removeSp;

После этого вновь происходит обращение к делегату strOp. На этот раз обращается строка с удаленными пробелами.

Цепочки вызовов являются весьма эффективным механизмом, поскольку они позволяют определить ряд методов, выполняемых единым блоком. Благодаря этому улучшается структура некоторых видов кода. Кроме того, цепочки вызовов имеют особое значение для обработки событий, как станет ясно в дальнейшем.

Ковариантность и контравариантность

Делегаты становятся еще более гибкими средствами программирования благодаря двум свойствам: ковариантности и контравариантности. Как правило, метод, передаваемый делегату, должен иметь такой же возвращаемый тип и сигнатуру, как и делегат. Но в отношении производных типов это правило оказывается не таким строгим благодаря ковариантности и контравариантности. В частности, ковариантность позволяет присвоить делегату метод, возвращаемым типом которого служит класс, производный от класса, указываемого в возвращаемом типе делегата. А контравариантность позволяет присвоить делегату метод, типом параметра которого служит класс, являющийся базовым для класса, указываемого в объявлении делегата.

Ниже приведен пример, демонстрирующий ковариантность и контравариантность.

// Продемонстрировать ковариантность и контравариантность.

using System;

class X {

  public int Val;

}

// Класс Y, производный от класса X.

class Y : X { }

// Этот делегат возвращает объект класса X и

// принимает объект класса Y в качестве аргумента,

delegate X ChangeIt(Y obj);

class CoContraVariance {

  // Этот метод возвращает объект класса X и

  // имеет объект класса X в качестве параметра,

  static X IncrA(X obj) {

    X temp = new X();

    temp.Val = obj.Val + 1;

    return temp;

  }

  // Этот метод возвращает объект класса Y и

  // имеет объект класса Y в качестве параметра,

  static Y IncrB(Y obj) {

    Y temp = new Y();

    temp.Val = obj.Val + 1;

    return temp;

  }

  static void Main() {

    Y Yob = new Y();

    // В данном случае параметром метода IncrA является объект класса X,

    // а параметром делегата Changelt — объект класса Y. Но благодаря

    // контравариантности следующая строка кода вполне допустима.

    ChangeIt change = IncrA;

    X Xob = change(Yob);

    Console.WriteLine("Xob: " + Xob.Val);

    // В этом случае возвращаемым типом метода IncrB служит объект класса Y,

    // а возвращаемым типом делегата Changelt — объект класса X.

    // Но благодаря ковариантности следующая строка кода

    // оказывается вполне допустимой,

    change = IncrB;

    Yob = (Y) change(Yob);

    Console.WriteLine("Yob: " + Yob.Val);

  }

}

Вот к какому результату приводит выполнение этого кода.

Xob: 1

Yob: 1

В данном примере класс Y является производным от класса X. А делегат ChangeIt объявляется следующим образом.

delegate X ChangeIt(Y obj);

Делегат возвращает объект класса X и принимает в качестве параметра объект класса Y. А методы IncrA() и IncrB() объявляются следующим образом.

static X IncrA(X obj)

static Y IncrB(Y obj)

Метод IncrA() принимает объект класса X в качестве параметра и возвращает объект того же класса. А метод IncrB() принимает в качестве параметра объект класса Y и возвращает объект того же класса. Но благодаря ковариантности и контравари-антности любой из этих методов может быть передан делегату ChangeIt, что и демонстрирует рассматриваемый здесь пример.

Перейти на страницу:

Герберт Шилдт читать все книги автора по порядку

Герберт Шилдт - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки kniga-online.club.


C# 4.0: полное руководство отзывы

Отзывы читателей о книге C# 4.0: полное руководство, автор: Герберт Шилдт. Читайте комментарии и мнения людей о произведении.


Уважаемые читатели и просто посетители нашей библиотеки! Просим Вас придерживаться определенных правил при комментировании литературных произведений.

  • 1. Просьба отказаться от дискриминационных высказываний. Мы защищаем право наших читателей свободно выражать свою точку зрения. Вместе с тем мы не терпим агрессии. На сайте запрещено оставлять комментарий, который содержит унизительные высказывания или призывы к насилию по отношению к отдельным лицам или группам людей на основании их расы, этнического происхождения, вероисповедания, недееспособности, пола, возраста, статуса ветерана, касты или сексуальной ориентации.
  • 2. Просьба отказаться от оскорблений, угроз и запугиваний.
  • 3. Просьба отказаться от нецензурной лексики.
  • 4. Просьба вести себя максимально корректно как по отношению к авторам, так и по отношению к другим читателям и их комментариям.

Надеемся на Ваше понимание и благоразумие. С уважением, администратор kniga-online.


Прокомментировать
Подтвердите что вы не робот:*
Подтвердите что вы не робот:*