Подтвердить что ты не робот

Когда правильно создать метод расширения?

У меня есть код, похожий на следующий:

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, из-за чего кажется, что он находится в неправильном месте. Правильное ли время для написания метода расширения? Каковы правильные сценарии создания методов расширения?

4b9b3361

Ответ 1

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

CONSIDER с использованием методов расширения в любом из следующих сценариев:

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

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

Ответ 2

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

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

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

Ответ 3

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

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

Ответ 4

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

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

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

Для руководящих принципов здесь для статьи Брэда

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

Ответ 5

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

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

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