Недостатки методов расширения? - PullRequest
28 голосов
/ 23 ноября 2008

Метод расширения - это действительно полезная функция, позволяющая добавлять множество функций в любой класс. Но мне интересно, есть ли какой-нибудь недостаток, который может доставить мне неприятности. Любые комментарии или предложения?

Ответы [ 7 ]

36 голосов
/ 23 ноября 2008
  • Способ импортирования методов расширения (т. Е. Всего пространства имен за раз) не является гранулированным. Вы не можете импортировать одно расширение из пространства имен, не получив все остальные.
  • Это не сразу очевидно из исходного кода, где определен метод. Это также преимущество - это означает, что вы можете сделать свой код похожим на остальные методы типа, даже если по какой-либо причине вы не можете поместить его в то же место. Другими словами, код проще понять на высоком уровне, но сложнее с точки зрения точно того, что выполняется. Я бы сказал, что это относится и к LINQ в целом.
  • У вас могут быть только методы расширения, но не свойства, индексаторы, операторы, конструкторы и т. Д.
  • Если вы расширяете класс третьей стороны и в более поздней версии они вводят новый метод с той же сигнатурой, вы не будете легко знать, что значение вашего кода вызова изменилось. Если новый метод очень аналогичен вашему расширению, но с немного различными граничными условиями (или чем-то еще), то это может привести к некоторым очень сложным ошибкам. Это вряд ли произойдет.
4 голосов
/ 23 ноября 2008

Пара вещей:

  • Не всегда ясно, откуда берется метод расширения, если вы не находитесь внутри VS.NET
  • Методы расширения не могут быть разрешены с помощью отражения или динамического поиска C # 4.0
3 голосов
/ 23 ноября 2008

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

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

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

2 голосов
/ 23 ноября 2008
  • Проверка нуля статическими методами отличается. Не обязательно лучше или хуже - но по-другому, и разработчик должен это понимать. Возможность вызова метода с нулевым значением может быть неожиданной и может (иногда) быть очень полезной.

  • Нет полиморфизма (хотя поддерживается перегрузка)

  • Вы можете попасть в беспорядок с неоднозначностью, если два типа расширения конфликтуют для типа источника (и ни один из них не квалифицируется как «лучший»). Затем компилятор отказывается использовать любой ... что означает, что добавление метода расширения в сборку A может нарушить * несвязанный код в сборке B. Я видел это пару раз ...

  • Вы не можете использовать с C # 2.0, поэтому, если вы пишете библиотеку для C # 2.0, это не поможет

  • Ему нужен [ExtensionAttribute] - поэтому, если вы пишете библиотеку для .NET 2.0, вы попадаете в рассол: если вы объявите свой собственный [ExtensionAttribute], он может конфликтовать с NET 3.5 звонящий

Не поймите меня неправильно - я большой фанат!

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

* = только для компилятора; код, который уже скомпилирован, будет в порядке

0 голосов
/ 05 мая 2019

Есть два разных сценария, в которых методы расширения вступают в игру:

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

    public interface IPointF{
        float X { get; }
        float Y { get; }
    }
    
    public struct PointF: IPointF{
        public PointF(float x, float y){
            X=x;Y=y;
        }
        public float X { get; private set; }
        public float Y { get; private set; }
    }
    
    public static class PointHelper{
        public static PointF ADD(this IPointF p, float val){
            return new PointF(p.x+val, p.y+val);
        }
    }
    

Таким образом, любой будущий пользователь может сэкономить много времени в кодировании, унаследовав IPoint.

0 голосов
/ 18 мая 2015

Мне сложно представить, чтобы добавить метод, не зная глубоко о существующем коде. Например, вы использовали сторонний класс, чтобы сделать что-то, что потребовало бы от вас расширения функциональности этого класса, учитывая, что вы не являетесь первоначальным разработчиком и у вас нет идей, как все устроено в учебный класс? Это почти бессмысленно делать так же, как бессмысленно водить машину, когда ты не видишь. В случае LINQ, где он реализован дизайнерами / кодами Microsoft, это имело большой смысл, поскольку они обладают знаниями о том, как сказать внутреннюю реализацию последовательности, и теперь они хотят расширить ее функциональность, добавив метод Count для подсчета всех элементы в последовательности. Сказав это, я хотел бы, чтобы кто-то оспорил меня неправильно, приведя реалистичный пример, где необходим метод расширения.

0 голосов
/ 23 ноября 2008

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

...