В C# не всегда можно расширить функционал класса путём наследования, т.к. существуют так называемые sealed классы, для которых оно запрещено. Также не всегда есть возможность доработать класс «под себя», т.к. нет доступа к исходному коду.
Поэтому, если такой класс всё-таки нуждается в изменении программист вынужден использовать «обходные пути» в виде паттернов или методов расширения. В этой статье мы поговорим о последних.
Механизм методов расширения позволяет добавить некоторому классу некий новый дополнительный функционал, не прибегая к наследованию или изменению исходного класса.
Методы расширения завоевали достаточную популярность, так как в ряде случаев представляют собой более эффективную альтернативу паттернам или классическому наследованию.
Например, добавим классу String методы позволяющие проверить является ли строка номером телефона в формате +7-123-456-78-90 и убрать из этого номера дефисы (чтобы получилось +71234567890).
Для этого создадим статический класс (для примера назовём его MyStringExtensions) и напишем в нём соответствующие статические методы, которые и будут являться собственными методами расширения.
Эти методы отличаются от обычных тем, что они обязательно принимают хотя бы один параметр в виде объекта того класса, который этот метод расширяет и перед этим параметром обязательно указывается ключевое слово this.
Ниже приведён исходный код класса с методами расширения, о которых мы говорили выше.
public static class MyStringExtensions { /// <summary> /// Проверка, является ли строка телефонным номером. /// </summary> /// <param name="input">Проверяемая строка.</param> /// <returns></returns> public static bool IsValidPhoneNumber(this string input) { string pattern = @"^\+7-\d{3}-\d{3}-\d{2}-\d{2}$"; Regex regex = new Regex(pattern); return regex.IsMatch(input); } /// <summary> /// Удаление дефисов из строки с телефонным номером. /// </summary> /// <param name="input">Строка с телефонным номером.</param> /// <returns></returns> public static string CompactPhoneNumber(this string input) { if (input.IsValidPhoneNumber()) { string pattern = @"-"; Regex regex = new Regex(pattern); return regex.Replace(input, String.Empty); } else { return String.Empty; } } }
В данном примере кода используются регулярные выражения, работа с которыми в C# уже была описана ранее в другой статье. Потому если читатель не знаком с ними, рекомендуется дополнительно прочитать статью «Работа с регулярными выражениями в C#».
Благодаря этим методам мы можем работать с телефонными номерами в формате строк как показано ниже:
string phone = Console.ReadLine(); Console.WriteLine(phone.IsValidPhoneNumber()); Console.WriteLine(phone.CompactPhoneNumber());
Важно отметить, что методы расширения работают только на уровне пространства имён.
То есть для использования методов расширения в другом пространстве имён, то пространство имён, которому они принадлежат нужно будет соответствующим образом импортировать.