2008-11-23 4 views
26

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

ответ

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

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

3

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

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

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

+1

@ дублированные подписи комментарий: Его неотъемлемый риск на многих других языках тоже, и люди управляют ОК. Хотя это все еще может быть недостатком, это маловероятно, в большинстве случаев, ИМО. – Chris 2008-11-23 06:25:56

4

Пара вещей:

  • Это не всегда ясно, где метод расширения происходит от, если вы не в VS.NET
  • Методы расширения не могут быть решены с помощью отражения или C# 4.0-х динамический поиск
+1

Вы можете найти методы расширения с помощью отражения. Найдите атрибут «ExtensionAttribute». Взгляните на http://stackoverflow.com/questions/299515/c-reflection-to-identify-extension-methods – Patrik 2008-11-23 12:58:06

+0

@Patrik - но вы не можете сделать это однозначно, так как вы не знаете, какие «приемы», следует считать. Иногда это имеет значение. – 2008-11-23 15:46:49

+1

@Patrik: То, что я имел в виду «разрешение», было: в то время как вы можете вызвать myType.extendedMethod(), вы не можете сделать это с помощью обычного кода отражения, то есть typeof (MyType) .GetMethod («extendedMethod»). Invoke (...) или динамический поиск, то есть динамический myType = new MyType(); myType.extendedMethod(); – 2008-11-26 15:02:35

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

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

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

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

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

Do не поймите меня неправильно, хотя - я большой поклонник!

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

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

0

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