Когда следует избегать методов расширения? - PullRequest
8 голосов
/ 07 июля 2010

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

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

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

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

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

Ответы [ 5 ]

5 голосов
/ 07 июля 2010

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

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

public static XElement ToXElement(this XmlElement element) { }

public static XmlElement ToXmlElement(this XElement element) { }

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

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

Например, разработчик недавно назначил этот метод расширения:

public static bool ParseYesNoBool(this string input) { }

Здесь есть две проблемы: во-первых, это будет появляться во всех строках приложения, даже если число строк, которые могут быть кандидатами в этом случае, очень мало. Итак, мы нарушили первое правило, так как оно бесполезно независимо от состояния. Точно так же, но во-вторых, потребитель этой функциональности ограничен одним парсером для одного конкретного соединителя с внешней системой. Поэтому продвижение функциональности, специфичной для реализации, в пространство имен общего пользования не имеет смысла. Это было понижено до вспомогательного метода в анализаторе.

Что касается читабельности и отладки, это просто неверно для разработчика любого разумного уровня квалификации.

1 голос
/ 07 июля 2010

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

1 голос
/ 07 июля 2010

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

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

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

0 голосов
/ 07 июля 2010

Методы расширения позволяют вам «добавлять» методы к существующим типам без создания нового производного типа, перекомпиляции или иного изменения исходного типа.

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

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

2) Забывание шаблона декоратора : Количество методов расширения, которые вы создаете длякласс превышает три.Я считаю, что легче организовать / общаться и поддерживать доменную / объектную модель с декорированными объектами, чем с расширенными объектами.Однако верно и обратное: если у декорированного объекта меньше четырех методов, я нахожу в своем проекте много почти «пустых» объектов.

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

0 голосов
/ 07 июля 2010

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

...