2010-07-06 3 views
8

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

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

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

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

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

+0

проверить эту статью ... http://www.vitalygorn.com/blog/post/2008/01/Extension-Methods---Extension-or-Confusion.aspx – Luiscencio

+0

@Luiscencio Спасибо за статью. Это немного длинный, поэтому я прочитаю его через несколько минут и отправлю обратно. Но это похоже на то, о чем мне было интересно. – spinon

ответ

5

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

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

public static XElement ToXElement(this XmlElement element) { } 

public static XmlElement ToXmlElement(this XElement element) { } 

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

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

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

public static bool ParseYesNoBool(this string input) { } 

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

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

+0

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

+0

@anon, почему DV? –

+0

Это оба прекрасных примера, когда они должны и не должны использоваться. Я видел аналогичные ситуации, когда функциональность объекта была добавлена ​​к объектам clR. Они проверяли специфические правила для объекта домена в типе и хотели просто добавить методы расширения к типу, чтобы упростить его. Я думаю, у меня есть еще один вопрос для SO, который я опубликую, а не попытаюсь вставить все это в этот комментарий? Плюс сделать его доступным для поиска в будущем. – spinon

0

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

+0

Мне просто интересно, как у вас может быть ситуация, когда это может быть плохо. Я думаю, если бы вы ставили методы, которые не имели ничего общего с классом или интерфейсом, сами по себе как метод расширения, который был бы одной из таких ситуаций. стр. Ваш босс звучит как настоящий мастер ООП: P – spinon

1

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

1

This discussion в разделе «Разделение конструкций гильдий» в разделе «Методы расширения» содержит несколько полезных советов. Я думаю, что соответствующая часть для вашего сценария:

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

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

+0

Я посмотрю, смогу ли я выкопать сценарий и опубликовать здесь измененное объяснение. – spinon

0

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

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

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

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

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

Смежные вопросы