среда, 6 августа 2008 г.

Extension methods (методы-расширения)

Одной из очень интересных фич .Net Framework 3.0 являются extension methods (методы-расширения).

Очень часто бывают такие ситуации, когда мы пользуемся чужим готовым классом, у которого не хватает нужных нам специфических методов. В этом случае существуют два решения:

  • Можно наследовать от исходного класса новый класс и писать нужные методы в дочернем классе, но у этого подхода есть явный минус: мы не можем использовать эти методы для экземпляров базового класса.
  • Можно создать статический метод, принимающий этот объект, над которым необходимо сделать какие-то операции. Плюс этого подхода в том, что мы можем использовать наш метод для экземпляров базового класса, но минус в том, что код начинает напоминать процедурный подход.


Следует заметить, что первый вариант недоступен в случае sealed-класса.

В C# 3.0 появляется возможность писать статические методы, но вызывать их как методы, принадлежащие исходному классу:

static class MyDateTimeExtensions
{
        public static string ToMyDate(this DateTime date)
        {
            return date.AddDays(1).ToLongDateString();
        }
}
Вызов будет, например, таким:

MessageBox.Show(DateTime.Now.ToMyDate());

Всё это, конечно, хорошо... Кроме того, что хочется использовать такую же функциональность в старых C# 2.0 проектах. Однако компилятор матерится и не компилирует. Но хочется. А как известно - если чего-то нельзя, но очень хочется - значит можно :)

Как оказалось - использование extension methods возможно после применения небольшого "хака" :) В проект необходимо добавить следующий код:

namespace System.Runtime.CompilerServices  
{  
  [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]  
  public class ExtensionAttribute : Attribute  
  {  
  }  
}

После чего приведенный выше пример начнет успешно компилироваться и - самое главное! - даже работать в проекте C# 2.0.

3 комментария:

  1. А какой версии .Net Framework в этом случае должен стоять на машине, где эта программа будет выполняться?

    ОтветитьУдалить
  2. Насколько я понимаю - это просто синтаксический сахар. Т.е. необходима, как минимум, новая версия компилятора при сборке проекта. А вот уже после того как мы получили файл-сборку, она сможет запуститься под вторым фреймворком.

    Фактически, третий фреймворк - это доработанный компилятор от второго фреймворка с поддержкой новых синтаксических конструкций плюс новые библиотеки. Соответственно, сборка собранная под третьим фреймворком, но не ссылающаяся на его сборки работать будет и под вторым фреймворком.

    P.S.: Проверил на машине где никогда не было третьего фреймворка - тестовый пример запустился и отработал как надо :)

    ОтветитьУдалить