В C# есть такая замечательная вещь, как
расширения(
extensions). Расширения позволяют «добавлять» методы в существующие типы, без создания производного типа, перекомпиляции или других способов вмешательства в его «внутренности».
К примеру у нас есть класс, отображающий имя и фамилию пользователя.
using System;
namespace TestExtensions
{
class Program
{
static void Main(string[] args)
{
var user = new User();
user.FirstName = "Имя";
user.LastName= "Фамилия";
user.Print();
}
}
public class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
public void Print()
{
Console.WriteLine("{0} {1}", FirstName, LastName);
}
}
}
Допустим, что выводить имя и фамилию в таком формате недопустимо, а надо использовать формат «FirstName: Имя; LastName: Фамилия». Конечно, можно сделать отдельную функцию, которая будет принимать имя и фамилию и выводить в нужном формате, но если использовать расширения, то использовать становится гораздо удобнее, да и код становится куда понятнее.
Чтобы использовать расширения, необходимо создать статический класс следующего вида
public static class MyExtensions
{
public static void CorrectPrint(this User user)
{
Console.WriteLine("FirstName: {0}; LastName: {1}", user.FirstName, user.LastName);
}
}
Расширением здесь является метод «
CorrectPrint», прописанное ключевое слово this позволяет ему обходится без параметров, при вызове его через объектную ссылку, так как this в списке параметров указывает на самого себя.
Дополним старый код расширением:
using System;
namespace TestExtensions
{
class Program
{
static void Main(string[] args)
{
var user = new User();
user.FirstName = "Имя";
user.LastName= "Фамилия";
user.Print();
user.CorrectPrint();
}
}
public static class MyExtensions
{
public static void CorrectPrint(this User user)
{
Console.WriteLine("FirstName: {0}; LastName: {1}", user.FirstName, user.LastName);
}
}
public class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
public void Print()
{
Console.WriteLine("{0} {1}", FirstName, LastName);
}
}
}
Как можно увидеть, новый метод вызывался прямо из объекта user “
user.CorrectPrint();”. Результат выполнения получится следующий:
Возможно, вам могло показаться, что использовать расширения можно только к своим классам, но это далеко не так. Приведу пример использования расширения к классу String: допустим, есть строка, содержащая набор чисел, разделённых пробелом, мне нужно узнать количество чисел в строке. Конечно, как и в предыдущем примере, можно обойтись без расширений, и написать что-то такое:
var str = "1 2 3 4 5 6 7 8 9 10";
Console.WriteLine(str.Split(' ').Count());
Но ведь это упрощенный пример, на практике, это может быть не такая тривиальная задача. А используя расширения, подсчет количества чисел можно реализовать так:
using System;
using System.Linq;
namespace TestExtensions
{
class Program
{
static void Main(string[] args)
{
var str = "1 2 3 4 5 6 7 8 9 10";
Console.WriteLine(str.CountNumbers());
}
}
public static class MyExtensions
{
public static int CountNumbers(this String str)
{
return str.Split(' ').Count();
}
}
}
И еще,
стоит обратить внимание, что расширения (extensions) это
единственный случай, когда разработчик
НЕ МОЖЕТ обойтись без использования статических классов.