Страница 222 из 502
<b>str = strOp("Это простой тест.");</b>
Экземпляр делегата strOp ссылается на метод ReplaceSpaces(), и поэтому вызывается именно этот метод.
Затем экземпляру делегата strOp присваивается ссылка на метод RemoveSpaces(), и с его помощью вновь вызывается указанный метод — на этот раз RemoveSpaces().
И наконец, экземпляру делегата strOp присваивается ссылка на метод Reverse(). А в итоге вызывается именно этот метод.
Главный вывод из данного примера заключается в следующем: в тот момент, когда происходит обращение к экземпляру делегата strOp, вызывается метод, на который он ссылается. Следовательно, вызов метода разрешается во время выполнения, а не в процессе компиляции.
Еще в версии C# 2.0 было внедрено специальное средство, существенно упрощающее синтаксис присваивания метода делегату. Это так называемое групповое преобразование методов, позволяющее присвоить имя метода делегату, не прибегая к оператору new или явному вызову конструктора делегата.
Ниже приведен метод Main() из предыдущего примера, измененный с целью продемонстрировать групповое преобразование методов.
<b>static void Main() {</b>
<b> // Сконструировать делегат, </b>
<b> // используя групповое преобразование методов. </b>
<b> StrMod strOp = ReplaceSpaces; // использовать групповое преобразование методов</b>
<b> string str;</b>
<b> // Вызвать методы с помощью делегата, </b>
<b> str = strOp("Это простой тест.");</b>
<b> Console.WriteLine("Результирующая строка: " + str);</b>
<b> Console.WriteLine();</b>
<b> strOp = RemoveSpaces; // использовать групповое преобразование методов </b>
<b> str = strOp("Это простой тест.");</b>
<b> Console.WriteLine("Результирующая строка: " + str);</b>
<b> Console.WriteLine() ;</b>
<b> strOp = Reverse; // использовать групповое преобразование методов </b>
<b> str = strOp("Это простой тест.");</b>
<b> Console.WriteLine("Результирующая строка: " + str);</b>
<b> Console.WriteLine() ;</b>
<b>}</b>
Обратите особое внимание на то, как создается экземпляр делегата strOp и как ему присваивается метод ReplaсеSpaces в следующей строке кода.
<b>strOp = RemoveSpaces; // использовать групповое преобразование методов</b>
В этой строке кода имя метода присваивается непосредственно экземпляру делегата strOp, а все заботы по автоматическому преобразованию метода в тип делегата "возлагаются" на средства С#. Этот синтаксис может быть распространен на любую ситуацию, в которой метод присваивается или преобразуется в тип делегата.
Синтаксис группового преобразования методов существенно упрощен по сравнению с прежним подходом к делегированию, поэтому в остальной части книги используется именно он.
В предыдущем примере использовались статические методы, но делегат может ссылаться и на методы экземпляра, хотя для этого требуется ссылка на объект. Так, ниже приведен измененный вариант предыдущего примера, в котором операции со строками инкапсулируются в классе StringOps. Следует заметить, что в данном случае может быть также использован синтаксис группового преобразования методов.
<b>// Делегаты могут ссылаться и на методы экземпляра.</b>
<b>using System;</b>
<b>// Объявить тип делегата, </b>
<b>delegate string StrMod(string str);</b>
<b>class StringOps {</b>
<b> // Заменить пробелы дефисами.</b>
<b> public string ReplaceSpaces(string s) {</b>
<b> Console.WriteLine("Замена пробелов дефисами."); </b>
<b> return s.Replace(' ', '-');</b>
<b> }</b>
<b> // Удалить пробелы.</b>
<b> public string RemoveSpaces(string s) {</b>
<b> string temp = "";</b>
<b> int i;</b>
<b> Console.WriteLine("Удаление пробелов.");</b>
<b> for(i=0; i < s.Length; i++)</b>
<b> if(s[i] != ' ') temp += s[i];</b>
<b> return temp;</b>
<b> }</b>
<b> // Обратить строку, </b>
<b> public string Reverse(string s) {</b>
<b> string temp = "";</b>
<b> int i, j;</b>
<b> Console.WriteLine("Обращение строки.");</b>
<b> for(j=0, i=s.Length-1; i >= 0; i--, j++) temp += s[i];</b>