Программирование >>  Программирование с использованием ajax 

1 ... 130 131 132 [ 133 ] 134 135 136 ... 396


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

Первый из этих методов расширения, т.е. метод ToTitleCase (), содержит больше всего кода, но является самым простым для понимания. Определяется он с помощью того же синтаксиса методов расширения, который демонстрировался ранее. Сразу же видно, что он будет применяться к объектам string, поскольку параметр экземпляра в нем выглядит как string. Еще у него имеется второй определенный параметр - forceLower. При вызове данного метода расширения, однако, использоваться будет только один параметр, поскольку параметр экземпляра будет браться из объекта, из которого это метод будет вызываться.

Код для этого метода начинается с подготовки входной строки путем отсечения всех пробельных символов и (необязательно) преобразования ее в нижний регистр:

public static string ToTitleCase(this string inputString, bool forceLower) {

inputString = inputString.Trim();

if (inputString == )

return ;

if (forceLower) {

inputString = inputString.ToLower();

Далее строка разбивается на массив отдельных слов, после чего выполняется разбор этого массива в цикле for, где с помощью объекта StringBuilder производится сборка результирующей строки:

string[] inputStringAsArray = inputString.Split( );

StringBuilder sb = new StringBuilder();

for (int i = 0; i < inputStringAsArray.Length; i++)

if (inputStringAsArray[i].Length > 0) {

Sb.AppendFormat( {0}{1} ,

inputStringAsArray[i].Substring(0, 1).ToUpper(), inputStringAsArray[i].Substring(1));

Напоследок результирующая строка возвращается. Последним символом в строке из-за обработки в цикле for является пробел, поэтому при ее возврате пробел отсекается:

return sb.ToString (О, sb.Length - 1);

Следующий метод расширения - ReverseString () - выглядит просто, но внешний вид может быть обманчив. В последовательности выполняемых им операций нет ничего сложного: сначала он сравнивает строку с массивом char, затем изменяет порядок элементов в этом массиве на обратный, потом преобразует измененный массив обратно в строку и возвращает ее. Однако метод, который он использует для изменения порядка элементов в массиве char на обратный, сам является методом расширения. Называется он Reverse () и определен в пространстве имен System. Linq следующим образом:

public static IEnumerable<TSource> Reverse<TSource> ( this IEnumerable<TSource> source);



Это определение выглядит сложнее, чем оно есть на самом деле, из-за того, что в нем используются обобщения. В методах расширения могут применяться параметры обобщенных типов во многом точно так же, как и в любых других методах. В методе Reverse () используется один единственный параметр обобщенного типа - TSource, а параметр экземпляра, применяемый в обобщенном методе, должен обязательно поддерживать интерфейс IEnumerable<TSource>. Внутри метода ReverseString () метод Reverse () вызывается для объекта типа char [ ]. Массив типа TSource поддерживает интерфейс IEnumerable<TSource> по определению, поэтому массив типа char поддерживает интерфейс IEnumerable<char>. А это значит, что вызываемая версия Reverse () на самом деле выглядит так:

public static IEnumerable<char> Reverse<char> (this IEnumerable<char> source);

В ReverseString () получающийся в результате интерфейс IEnumerable<char> преобразуется обратно в объект char [ ] за счет вызова его метода ТоАггау (), а сам этот объект char [ ] используется в конструкторе нового объекта string. Этот последний объект string, наконец, возвращается:

public static string ReverseString(this string inputString) {

return new string(inputString.ToCharArray().Reverse().ToArrayO);

В пространстве имен System. Linq содержится много методов расширения, большинство из которых предназначены для использования с технологией LINQ, как будет показано позже в этой книге. Многие из них, однако, могут также быть полезными и в других ситуациях, одна из которых и была продемонстрирована здесь.

Просмотреть эти методы расширения можно с помощью IntelliSense при условии, если было импортировано пространство имен System,Linq (которое импортируется по умолчанию). Однако на данном этапе лучисе пока не деяать этого, поскольку многие из таких методов основаны на использовании лямбда-выражений, о которых более подробно рассказывается в следующем разделе.

Последний метод расширения в рассматриваемом примере, т.е. ToStringReversed (), является примером более общего метода расширения. Вместо параметра экземпляра типа string он принимает параметр экземпляра типа object. Это значит, что он может вызываться для любого объекта, и будет появляться в окне IntelliSense для каждого используемого объекта. В этом методе можно делать не так уж много из-за ограниченности в предположениях касательно того, какой объект может использоваться. В частности, в нем можно либо применять операцию is, либо пытаться выполнять преобразование для выяснения того, к какому типу относится параметр экземпляра и действовать соответствующим образом, или же, как было сделано в этом примере, использовать базовую функцию, которая поддерживается всем объектами, т.е. метод ToStringО:

public static string ToStringReversed(this object inputObject) {

return inputObject.ToString().ReverseString();

Здесь метод ToStringReversed () просто вызывает метод ToString () для своего параметра экземпляра и изменяет порядок элементов в нем на обратный с помощью описанного ранее метода ReverseString (). В примере клиентского приложения метод ToStringReversed () вызывается для переменной int, что приводит к получению строкового представления целого числа с идущими в нем в обратном порядке цифрами.



Методы расширения, пригодные для использования с множеством типов, могут быть очень полезными. Еще не стоит забывать и о возможности определения обобщенных методов расширения, в которых на допустимые для использования типы можно устанавливать ограничения, как показывалось в главе 12.

Лямбда-выражения

Лямбда-выражения (lambda expressions) являются новой конструкцией в С# 3.0 и могут упрощать некоторые аспекты программирования на языке С#, особенно в случае использования в сочетании с технологией LINQ. Поначалу их осваивание может вызывать сложности, в основном из-за того, что они являются очень гибкими в отношении способов их применения. Больше всего пользы они приносят тогда, когда используются в сочетании с другими механизмами С#, например, с анонимными методами. Если не брать технологию LINQ, которая будет рассматриваться позже в этой книге, анонимные методы являются наилучшей отправной точкой для изучения этой темы. Поэтому сначала вкратце вспомним, как работают анонимные методы.

Краткое повторение анонимных методов

в главе 13 уже рассказывалось об анонимных методах, т.е. методах, которые предоставляются внутристрочно в местах, где в противном случае должна была бы идти переменная типа делегата. При добавлении обработчика событий для какого-то события необходимо выполнить перечисленные ниже шаги.

1. Определить метод обработчика событий, причем так, чтобы его возвращаемый тип и параметры совпадали с возвращаемым типом и параметрами делегата, требуемого для подписываемого события.

2. Объявить переменную с типом делегата, используемого для события.

3. Инициализировать переменную делегата экземпляром типа делегата, который ссылается на метод обработчика событий.

4. И, наконец, добавить переменную делегата в список подписчиков события.

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

Именно это и было сделано при применении следующего кода в главе 13:

Timer myTimer = new Timer(lOO);

myTimer.Elapsed += new ElapsedEventHandler(WriteChar) ;

В этом коде осуществлятся подписка на событие Elapsed объекта Timer. Это событие подразумевает использование делегата типа ElapsedEventHandler, экземпляр которого и создается с помощью идентификатора метода WriteChar. В результате здесь получается, что при генерации объектом Timer события Elapsed будет вызываться метод WriteChar (). То, какие параметры будут передаваться методу WriteChar (), зависит от типа параметров, определенных в делегате ElapsedEventHandler, и значений, которые будут поступать из кода того объекта Timer, который сгенерировал событие.

На самом деле, компилятор С# сможет достигать точно такого же результата и с помощью даже меньшего количества кода:

myTimer.Elapsed += WriteChar;



1 ... 130 131 132 [ 133 ] 134 135 136 ... 396

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика