Что такого хорошего в методах расширения?

Возможный дубликат:
​​Какие преимущества Вы нашли способы расширения?

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

Почему в .NET были введены методы расширения? Какие преимущества они предоставляют, кроме того, что они делают вещи красивыми (и под «красивыми» я имею в виду «обманчиво похожие на методы экземпляров»)?

Для меня любой код, использующий такой метод расширения:

Thing initial = GetThing();
Thing manipulated = initial.SomeExtensionMethod();

вводит в заблуждение, потому что подразумевает, что SomeExtensionMethod является членом экземпляра Thing, что вводит разработчиков в заблуждение, заставляя их поверить (по крайней мере, на интуитивном уровне ... вы можете отрицать это, но я определенно заметил это), что (1) SomeExtensionMethod, вероятно, реализован эффективно, и (2) поскольку SomeExtensionMethod на самом деле выглядит как часть класса Thing, он наверняка останется действительным, если Thing будет пересмотрен в какой-то момент в будущем (пока автор Thing знает, что он / она делает).

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

Все мы знаем, что это легко может быть:

Thing initial = GetThing();
Thing manipulated = SomeNonExtensionMethod(initial);

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

Что мне не хватает? Почему существуют методы расширения?


person Dan Tao    schedule 18.11.2009    source источник
comment
stackoverflow.com/ questions / 487904 /   -  person Marek Karbarz    schedule 19.11.2009
comment
@Zarembisty: Спасибо, я честно искал дубликат, прежде чем опубликовать это, но каким-то образом не нашел его. Если люди хотят закрыть это, это понятно.   -  person Dan Tao    schedule 19.11.2009
comment
Я обнаружил, что поиск SO был так себе; Google всегда находит ответы (и, к счастью, все больше и больше ответов указывают на SO)   -  person Marek Karbarz    schedule 19.11.2009


Ответы (6)


Методы расширения были необходимы для того, чтобы Linq работал так же чисто, как и с цепочкой методов. Если вам нужно использовать «длинную» форму, это приводит к тому, что вызовы функций и параметры отделяются друг от друга, что затрудняет чтение кода. Сравнивать:

IEnumerable<int> r = list.Where(x => x > 10).Take(5)

против

// What does the 5 do here?
IEnumerable<int> r = Enumerable.Take(Enumerable.Where(list, x => x > 10), 5);

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

person Mark Byers    schedule 18.11.2009
comment
Я знаю, что этот вопрос закрыт, но это был мой любимый ответ. - person Dan Tao; 19.11.2009
comment
Наряду с цепочкой, я хочу добавить еще одну вещь, которая поможет нам расширить поведение класса без фактического изменения класса. Следовательно, это помогает нам использовать принцип открытости и закрытости - класс должен быть открыт для расширения, но закрыт для модификации. - person Shobhit Walia; 26.02.2017

Я думаю, что главный плюс - это обнаруживаемость. Введите initial и точку, и у вас будет все, что вы можете с этим сделать. Гораздо сложнее найти статические методы, спрятанные в каком-то классе где-то еще.

person Fredrik Mörk    schedule 18.11.2009
comment
Однако не является ли это скорее следствием функциональности Visual Studio, а не неотъемлемым преимуществом методов расширения как части C # /. NET? - person Dan Tao; 19.11.2009
comment
@Dan: да, если вы используете другой редактор, который не обнаруживает методы расширения и не показывает их, как это делает Intellisense, это преимущество пропадает. - person Fredrik Mörk; 19.11.2009

Прежде всего, в случае Thing manipulated = SomeNonExtensionMethod(initial); SomeNonExtensionMethod основан на тех же предположениях, что и в случае Thing manipulated = initial.SomeExtensionMethod();. Вещь может измениться, SomeExtensionMethod может сломаться. Это жизнь для нас, программистов.

Во-вторых, когда я вижу Thing manipulated = initial.SomeExtensionMethod();, он не сообщает мне, где именно реализован SomeExtensionMethod (). Вещь могла унаследовать его от TheThing, который наследует его от TheOriginalThing. Так что «вводящий в заблуждение» аргумент ни к чему не приводит. Готов поспорить, IDE позаботится о том, чтобы привести вас к нужному источнику, не так ли?

Что в этом хорошего? Это делает код более последовательным. Если он работает со строкой, похоже, что он был членом строки. Уродливо иметь несколько MyThing.doThis() методов и несколько static ThingUtil.doSomethingElse(Mything thing) методов в другом классе.

person Erich Kitzmueller    schedule 18.11.2009
comment
К вашему первому пункту: я хочу сказать, что на самом деле это одно и то же, но версия SomeNonExtensionMethod менее вводит в заблуждение, потому что не заставляет вас думать, что метод на самом деле является частью определения класса. - person Dan Tao; 19.11.2009
comment
Ко второму пункту: по крайней мере, если вы вызываете член экземпляра, вы знаете, что он реализован внутри класса, что означает, что, по крайней мере, у него есть доступ к защищенным членам, и должен быть гарантированно продолжен работать всякий раз, когда класс обновляется. - person Dan Tao; 19.11.2009
comment
К вашему последнему пункту: говорить, что статические методы работают с объектом, некрасиво, кажется мне очень субъективным. Мне трудно увидеть выгоду. Я мог бы пожелать, чтобы команда разработчиков C # разрешила заменять фигурные скобки квадратными скобками, потому что мне это кажется более привлекательным; это не значит, что они сделают так, чтобы улучшить язык. - person Dan Tao; 19.11.2009
comment
Дэн: Во-первых: я не думаю, что имеет большое значение, является ли это частью определения класса или нет. Либо он работает как положено, либо нет. - person Erich Kitzmueller; 19.11.2009
comment
Дэн: Второй: Как сторонний наблюдатель, я ничего не знаю о защищенных членах. Меня не волнует, как SomeExtensionMethod () делает то, что делает. Слишком много знаний об этом приводит к предположениям, возможно, к скрытым зависимостям. WOrk всякий раз, когда класс обновляется: я думаю, вы используете методы расширения для очень стабильных классов, таких как строка. Вы бы не использовали это для своих собственных классов, поскольку вместо этого вы всегда можете изменить их. - person Erich Kitzmueller; 19.11.2009
comment
Дэн: В-третьих: ThingUtil.staticDoSomething (Thing it) уродлив, потому что это антипаттерн функциональной декомпозиции. Технически методы расширения не лучше, но по крайней мере менее заметны. - person Erich Kitzmueller; 19.11.2009

ТАК, вы можете расширить чужой класс. не твое ... в этом преимущество. (и вы можете сказать ... о, я бы хотел, чтобы они реализовали это / это .... вы просто сделаете это сами ..)

person Dani    schedule 18.11.2009
comment
Черт, @Zarembisty такой прав - иди туда, как он написал. вы получите все там! stackoverflow.com/questions/487904/… - Зарембисты. - person Dani; 19.11.2009
comment
Я хочу сказать, что они не дают вам больше возможностей, чем простое использование статических методов. - person Dan Tao; 19.11.2009

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

Linq часто этим пользуется.

Отличный способ украсить классы дополнительными функциями. Наиболее эффективен при применении к интерфейсу, а не к конкретному классу. Тем не менее, это хороший способ расширить классы Framework.

person Keith Nicholas    schedule 18.11.2009

Это просто удобный синтаксический сахар, так что вы можете вызывать метод с тем же синтаксисом, независимо от того, действительно ли он является частью класса. Если сторона A выпускает библиотеку, а сторона B выпускает материал, который использует эту библиотеку, проще просто вызвать все с помощью class.method (args), чем запоминать, что вызывается с помощью метода (class, args) по сравнению с class.method (аргументы).

person dsimcha    schedule 18.11.2009