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

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

Мы начали использовать С# (.NET 3.0), и мне интересно, как вы, ребята, используете методы расширения? Когда вы их используете?

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

4b9b3361

Ответ 1

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

  • Методы расширения не могут использоваться для переопределения существующих методов.

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

  • Концепция методов расширения не может применяться к полям, свойствам или событиям

  • Используйте методы расширения экономно.... чрезмерное использование может быть плохим!

Ответ 2

Время для использования методов расширения:

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

Пример второй точки; у вас может быть метод расширения на IList<T> (например, Sort), который может быть написан полностью с использованием существующих членов IList<T>... так зачем заставлять кого-нибудь писать что-нибудь? Это базовый блок LINQ и позволил Microsoft обеспечить гораздо больше функциональности, не нарушая ничего.

Время < не использовать методы расширения:

  • когда полиморфизм является критическим; вы не можете гарантировать, что ваш код будет версией, которая будет выполняться с использованием метода расширения, поскольку методы, непосредственно относящиеся к типу, имеют приоритет
  • когда вам нужен доступ к частным/защищенным членам

Ответ 3

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

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

Одно место, которое я часто использую методы расширения, - это перечисления [Flags]. Когда у вас есть перечисление на основе флага, существует довольно большое выражение, необходимое для определения того, имеет ли значение перечисления определенный набор флагов. И поэтому я строю следующий метод расширения всякий раз, когда я строю перечисление [Flags]:

[Flags]
public enum MyEnum
{
    FlagA,
    FlagB,
    // etc.
}

public static class MyEnumExt
{
    public static bool HasFlags(this MyEnum item, MyEnum query)
    {
        return ((item & query) == query);
    }
}

Таким образом, мой код выглядит следующим образом:

MyEnum flags = MyEnum.FlagA;
if(flags.HasFlags(MyEnum.FlagA))
{
  // handle FlagA
}

Вместо

MyEnum flags = MyEnum.FlagA;
if((flags & MyEnum.FlagA) == MyEnum.FlagA)
{
  // handle FlagA
}

Ответ 4

Эта ссылка http://geekswithblogs.net/BlackRabbitCoder/archive/2010/04/26/c-extension-methods---to-extend-or-not-to-extend.aspx дает хорошие рекомендации о том, когда использовать методы расширения, а когда нет.

Чтобы процитировать эту статью:

Хороший метод расширения должен:
- Применить к любому возможному экземпляру типа, который он расширяет.
- Упростить логику и улучшить читаемость/ремонтопригодность.
- Применить к конкретному типу или интерфейсу.
- быть изолированным в пространстве имен, чтобы он не загрязнял IntelliSense.

Ответ 5

Честно говоря, я бы сказал, что легче сказать, когда это НЕ хорошая идея, тогда, когда это хорошая идея.

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

При рассмотрении вопроса о том, следует ли создавать метод расширения, помните принципы SOLID.

S ingle Ответственность: - Вы почти всегда, по крайней мере, сгибаете принцип единой ответственности > с помощью метода расширения, потому что вы привязываетесь к тому, что уже есть > класс (который вы либо не контролируете, либо слишком боитесь касаться).

O ручка/принцип закрытия: - Методы расширения также не являются чрезмерными, что означает, что ваш метод не может быть "адекватно" открыт для расширения.

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

I принцип сегрегации -Хотя вы можете "расширить" интерфейс, вы должны предоставить конкретную реализацию для этого расширения. Таким образом, вы не можете запрограммировать интерфейs > , который реализуется по-разному в другом контексте (например, Unit Test)

D принцип инверсии вершин - Если ваш код имеет какие-либо зависимости, как вы собираетесь раскрывать эти зависимости для заводов и модульных тестов (принцип инверсии зависимостей)?

Наконец, методы расширения - это просто статические методы, носящие новое платье. Таким образом, все трудности со статическими методами (например, безопасность потока, сборка мусора и т.д.) идут вместе с методами расширения при их реализации.

Итак, я долго и долго думал о написании метода в качестве расширения и пересмотреть с помощью factory и базового вспомогательного класса.

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