Рейтинговые книги
Читем онлайн C# 4.0: полное руководство - Герберт Шилдт

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 123 124 125 126 127 128 129 130 131 ... 294

    Console.WriteLine();

    strOp = new StrMod(Reverse);

    str = strOp("Это простой тест.");

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

  }

}

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

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

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

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

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

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

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

Рассмотрим данный пример более подробно. В его коде сначала объявляется делегат StrMod типа string, как показано ниже.

delegate string StrMod(string str);

Как видите, делегат StrMod принимает один параметр типа string и возвращает одно значение того же типа.

Далее в классе DelegateTest объявляются три статических метода с одним параметром типа string и возвращаемым значением того же типа. Следовательно, они соответствуют делегату StrMod. Эти методы видоизменяют строку в той или иной форме. Обратите внимание на то, что в методе Rep la се Spaces() для замены пробелов дефисами используется один из методов типа string — Replace().

В методе Main() создается переменная экземпляра strOp ссылочного типа StrMod и затем ей присваивается ссылка на метод ReplaceSpaces(). Обратите особое внимание на следующую строку кода.

StrMod strOp = new StrMod(ReplaceSpaces);

В этой строке метод ReplaceSpaces() передается в качестве параметра. При этом указывается только его имя, но не параметры. Данный пример можно обобщить: при получении экземпляра делегата достаточно указать только имя метода, на который должен ссылаться делегат. Ясно, что сигнатура метода должна совпадать с той, что указана в объявлении делегата. В противном случае во время компиляции возникнет ошибка.

Далее метод ReplaceSpaces() вызывается с помощью экземпляра делегата strOp, как показано ниже.

str = strOp("Это простой тест.");

Экземпляр делегата strOp ссылается на метод ReplaceSpaces(), и поэтому вызывается именно этот метод.

Затем экземпляру делегата strOp присваивается ссылка на метод RemoveSpaces(), и с его помощью вновь вызывается указанный метод — на этот раз RemoveSpaces().

И наконец, экземпляру делегата strOp присваивается ссылка на метод Reverse(). А в итоге вызывается именно этот метод.

Главный вывод из данного примера заключается в следующем: в тот момент, когда происходит обращение к экземпляру делегата strOp, вызывается метод, на который он ссылается. Следовательно, вызов метода разрешается во время выполнения, а не в процессе компиляции.

Групповое преобразование делегируемых методов

Еще в версии C# 2.0 было внедрено специальное средство, существенно упрощающее синтаксис присваивания метода делегату. Это так называемое групповое преобразование методов, позволяющее присвоить имя метода делегату, не прибегая к оператору new или явному вызову конструктора делегата.

Ниже приведен метод Main() из предыдущего примера, измененный с целью продемонстрировать групповое преобразование методов.

static void Main() {

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

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

  StrMod strOp = ReplaceSpaces; // использовать групповое преобразование методов

  string str;

  // Вызвать методы с помощью делегата,

  str = strOp("Это простой тест.");

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

  Console.WriteLine();

  strOp = RemoveSpaces; // использовать групповое преобразование методов

  str = strOp("Это простой тест.");

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

  Console.WriteLine() ;

  strOp = Reverse; // использовать групповое преобразование методов

  str = strOp("Это простой тест.");

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

  Console.WriteLine() ;

}

Обратите особое внимание на то, как создается экземпляр делегата strOp и как ему присваивается метод ReplaсеSpaces в следующей строке кода.

strOp = RemoveSpaces; // использовать групповое преобразование методов

В этой строке кода имя метода присваивается непосредственно экземпляру делегата strOp, а все заботы по автоматическому преобразованию метода в тип делегата "возлагаются" на средства С#. Этот синтаксис может быть распространен на любую ситуацию, в которой метод присваивается или преобразуется в тип делегата.

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

Применение методов экземпляра в качестве делегатов

В предыдущем примере использовались статические методы, но делегат может ссылаться и на методы экземпляра, хотя для этого требуется ссылка на объект. Так, ниже приведен измененный вариант предыдущего примера, в котором операции со строками инкапсулируются в классе StringOps. Следует заметить, что в данном случае может быть также использован синтаксис группового преобразования методов.

// Делегаты могут ссылаться и на методы экземпляра.

using System;

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

delegate string StrMod(string str);

class StringOps {

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

  public string ReplaceSpaces(string s) {

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

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

  }

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

  public string RemoveSpaces(string s) {

    string temp = "";

    int i;

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

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

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

    return temp;

  }

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

  public string Reverse(string s) {

    string temp = "";

    int i, j;

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

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

    return temp;

  }

}

class DelegateTest {

  static void Main() {

    StringOps so = new StringOps(); // создать экземпляр

                   // объекта класса StringOps

    // Инициализировать делегат.

    StrMod strOp = so.ReplaceSpaces;

    string str;

    // Вызвать методы с помощью делегатов,

    str = strOp("Это простой тест.");

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

    Console.WriteLine();

    strOp = so.RemoveSpaces;

    str = strOp("Это простой тест.");

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

    Console.WriteLine();

    strOp = so.Reverse;

    str = strOp("Это простой тест.");

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

  }

}

Результат выполнения этого кода получается таким же, как и в предыдущем примере, но на этот раз делегат обращается к методам по ссылке на экземпляр объекта класса StringOps.

Групповая адресация

Одним из самых примечательных свойств делегата является поддержка групповой адресации. Попросту говоря, групповая адресация — это возможность создать список, или цепочку вызовов, для методов, которые вызываются автоматически при обращении к делегату. Создать такую цепочку нетрудно. Для этого достаточно получить экземпляр делегата, а затем добавить методы в цепочку с помощью оператора + или +=. Для удаления метода из цепочки служит оператор - или -=. Если делегат возвращает значение, то им становится значение, возвращаемое последним методом в списке вызовов. Поэтому делегат, в котором используется групповая адресация, обычно имеет возвращаемый тип void.

1 ... 123 124 125 126 127 128 129 130 131 ... 294
На этой странице вы можете бесплатно читать книгу C# 4.0: полное руководство - Герберт Шилдт бесплатно.
Похожие на C# 4.0: полное руководство - Герберт Шилдт книги

Оставить комментарий