Когда правильно создать метод расширения? - PullRequest
13 голосов
/ 01 февраля 2011

У меня есть фрагмент кода, подобный следующему:

public class ActivityHelper
{
    public void SetDate(IList<Activity> anActivityList)
    {
        foreach(Activity current in anActivityList)
        {
            current.Date = DateTime.Now;
        }
    }
    //More methods, properties, fields, etc...
}

Это может быть легко преобразовано в метод расширения. Например:

public static void SetDate(this IList<Activity> aList)
{
    foreach(Activity current in anActivityList)
    {
        current.Date = DateTime.Now;
    }
}

Исходная функция не использует какие-либо данные или методы, специфичные для экземпляра, из класса ActivityHelper, что создает впечатление, что она находится в неправильном месте. Это правильное время, чтобы написать метод расширения? Каковы правильные сценарии для создания методов расширения?

Ответы [ 5 ]

12 голосов
/ 01 февраля 2011

Брэд Адамс написал о рекомендациях по разработке методов расширения :

РАССМОТРИТЕ, используя методы расширения в любом из следующих сценариев:

  • Предоставить вспомогательные функциональные возможности, относящиеся к каждой реализации интерфейса, если указанные функциональные возможности могут быть записаны в терминах основного интерфейса. Это связано с тем, что конкретные реализации не могут быть назначены интерфейсам. Например, операторы LINQ to Objects реализованы как методы расширения для всех типов IEnumerable. Таким образом, любая реализация IEnumerable <> автоматически поддерживает LINQ.

  • Когда метод экземпляра вводит зависимость от какого-либо типа, но такая зависимость нарушает правила управления зависимостями. Например, зависимость от String для System.Uri, вероятно, нежелательна, и поэтому метод экземпляра String.ToUri (), возвращающий System.Uri, был бы неправильным проектом с точки зрения управления зависимостями. Статический метод расширения Uri.ToUri (эта строка str), возвращающий System.Uri, был бы намного лучше.

6 голосов
/ 01 февраля 2011

Я думаю, что методы расширения подходят только в том случае, если есть веская причина сделать метод методом расширения.

Если типом является тот, которым вы не управляете, и метод должен казаться неотъемлемым для типа, или если есть веская причина не использовать метод непосредственно для типа (например, создать нежелательный тип)зависимости), тогда может быть уместен метод расширения.

Лично, если ожидание пользователя вашего API уже будет использовать класс ActivityHelper при работе с коллекциями Activity, то я, вероятно, не буду создаватьметод расширения для этого.Стандартный метод без расширения будет на самом деле более простым API, поскольку его легко понять и обнаружить.Методы расширения сложны с точки зрения использования - вы вызываете метод, который "выглядит так", что он существует где-то, а не там, где он действительно существует.Хотя это может упростить синтаксис, оно снижает удобство сопровождения и возможности обнаружения.

4 голосов
/ 01 февраля 2011

По моему опыту методы расширения работают лучше всего, когда они:

  • У меня нет побочных эффектов (большинство методов расширения, написанных моей командой, которые имеют побочные эффекты, мы в итоге удалили, потому что они вызвали больше проблем, чем помогли)
  • Предложите функциональность, которая применяется к каждому возможному экземпляру или значению типа, который они расширяют. (Опять же, приведя пример из моей команды, string.NormalizeUrl() не подходит, потому что в любом случае не все строки являются даже URL-адресами)
0 голосов
/ 01 февраля 2011

По сути, методы расширения обеспечивают более свободный синтаксис стиля для методов Helper. Это переводит в способность на вид добавить функциональность к типам или всем реализациям интерфейсов.

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

Однако, я думаю, это может быть удобно, если ваши методы будут использованы IntelliSense ...: -)

0 голосов
/ 01 февраля 2011

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

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

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

Для руководства здесь к статье Брэда

http://blogs.msdn.com/b/brada/archive/2009/01/12/framework-design-guidelines-extension-methods.aspx

...