Расширения (extensions) в C#

В 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) это единственный случай, когда разработчик НЕ МОЖЕТ обойтись без использования статических классов.

Добавить комментарий