Я смотрю на компонент MvcContrib Grid, и меня восхищает, но в то же время отталкивает синтаксический прием, используемый в синтаксисе Grid :
.Attributes(style => "width:100%")
Синтаксис выше устанавливает атрибут стиля сгенерированного HTML в width:100%
. Теперь, если вы обратите внимание, «стиль» нигде не указан. Это выводится из имени параметра в выражении! Я должен был покопаться в этом и найти, где происходит «волшебство»:
Hash(params Func<object, TValue>[] hash)
{
foreach (var func in hash)
{
Add(func.Method.GetParameters()[0].Name, func(null));
}
}
Таким образом, код использует формальное время компиляции, имя параметров для создания словаря пар имя-значение атрибута. Полученная синтаксическая конструкция действительно очень выразительна, но в то же время очень опасна.
Общее использование лямбда-выражений позволяет заменять имена, используемые без побочных эффектов. Я вижу пример в книге, который говорит, что collection.ForEach(book => Fire.Burn(book))
я знаю, что могу написать в своем коде, collection.ForEach(log => Fire.Burn(log))
и это означает то же самое . Но с синтаксисом MvcContrib Grid здесь я неожиданно обнаружил код, который активно просматривает и принимает решения на основе имен, выбранных для моих переменных!
Так это обычная практика с сообществом C # 3.5 / 4.0 и любителями лямбда-выражений? Или мне не стоит беспокоиться о мошенниках?
источник
Ответы:
Это имеет плохое взаимодействие. Например, рассмотрим этот пример C # - F #
C #:
F #:
Результат:
«arg» печатается (не «yadda»).
В результате разработчики библиотек должны либо избегать такого рода «злоупотреблений», либо, по крайней мере, предоставлять «стандартную» перегрузку (например, которая принимает имя строки в качестве дополнительного параметра), если они хотят иметь хорошее взаимодействие между языками .Net.
источник
Я нахожу это странным не столько из-за названия , сколько из-за того , что лямбда не нужна ; он может использовать анонимный тип и быть более гибким:
Этот шаблон используется в большинстве ASP.NET MVC (например) и имеет другое применение ( предостережение , обратите внимание также на мысли Айенде, если имя является магическим значением, а не специфичным для вызывающего)
источник
HtmlAttributes
класс с ожидаемыми атрибутами (для intellisense) и просто игнорировать атрибуты соnull
значениями ...Просто хотел скинуть по моему мнению (я автор компонента сетки MvcContrib).
Это определенно злоупотребление языком - нет сомнений. Однако я бы не стал считать это противоречащим интуиции - когда вы смотрите на вызов,
Attributes(style => "width:100%", @class => "foo")
я думаю, что это довольно очевидно, что происходит (это, конечно, не хуже, чем подход с анонимным типом). С точки зрения интеллигенции, я согласен, что это довольно непрозрачно.
Для тех, кто заинтересован, некоторая справочная информация о его использовании в MvcContrib ...
Я добавил это в таблицу в качестве личного предпочтения - мне не нравится использование анонимных типов в качестве словарей (параметр, который принимает «объект», столь же непрозрачен, как параметр, принимающий параметры Func []), и инициализатор коллекции словаря скорее многословный (я также не фанат многословных беглых интерфейсов, например, необходимости связывать воедино множественные вызовы атрибута («style», «display: none»). Attribute («class», «foo») и т. д.)
Если бы C # имел менее подробный синтаксис для литералов словаря, то я бы не стал включать этот синтаксис в компонент сетки :)
Я также хочу отметить, что использование этого в MvcContrib совершенно необязательно - это методы расширения, которые обертывают перегрузки, которые вместо этого принимают IDictionary. Я думаю, что важно, чтобы, если вы предоставляете такой метод, вы также поддерживали более «нормальный» подход, например, для взаимодействия с другими языками.
Кроме того, кто-то упомянул «издержки на рефлексию», и я просто хотел отметить, что при таком подходе не так много служебной информации - не требуется никакого отражения во время выполнения или компиляции выражений (см. Http://blog.bittercoder.com /PermaLink,guid,206e64d1-29ae-4362-874b-83f5b103727f.aspx ).
источник
я бы предпочел
Это намного более явно и стандартно, и ничего не получается с помощью лямбд.
источник
html.Attributes.Add("style", "width:100%");
не читается так хорошо, какstyle = "width:100%"
(фактический сгенерированный html), в то времяstyle => "width:100%"
как очень близко к тому, как это выглядит в результирующем HTML.Добро пожаловать в Rails Land :)
В этом нет ничего плохого, если вы знаете, что происходит. (Это когда такая вещь плохо документирована, поэтому возникает проблема).
Вся структура Rails построена на идее соглашения по конфигурации. Обозначение вещей определенным образом вводит вас в соглашение, которое они используют, и вы получаете множество функциональных возможностей бесплатно. Следование соглашению об именах поможет вам двигаться быстрее. Все это работает блестяще.
Еще одно место, где я видел такой трюк, - это утверждения вызовов методов в Moq. Вы проходите в лямбду, но лямбда никогда не выполняется. Они просто используют выражение, чтобы убедиться, что вызов метода произошел, и выдают исключение, если нет.
источник
Это ужасно на нескольких уровнях. И нет, это не похоже на Ruby. Это злоупотребление C # и .NET.
Было много предложений о том, как сделать это более простым способом: кортежи, анонимные типы, свободный интерфейс и так далее.
То, что делает это настолько плохим, - то, что его просто воображают для его собственного блага:
Что происходит, когда вам нужно вызвать это из Visual Basic?
.Attributes(Function(style) "width:100%")
Это абсолютно противоречит интуиции, и intellisense мало поможет в выяснении того, как передать материал.
Это излишне неэффективно.
Никто не будет иметь ни малейшего понятия, как его поддерживать.
Какой тип аргумента используется для атрибутов? это так
Func<object,string>
? Как это намерение раскрывается? Что ваша документация intellisense собирается сказать: «Пожалуйста, не обращайте внимания на все значения объекта»?Я думаю, что вы полностью оправдываете чувство отвращения.
источник
Я нахожусь в лагере "синтаксического блеска", если они четко это документируют, и это выглядит чертовски круто, то с этим почти нет проблем, imo!
источник
Оба из них. Это злоупотребление лямбда-выражениями И синтаксическим блеском.
источник
Я почти никогда не сталкивался с такого рода использованием. Я думаю, что это "неуместно" :)
Это не обычный способ использования, он не согласуется с общими соглашениями. Этот вид синтаксиса имеет плюсы и минусы, конечно:
Cons
Pros
Итог - в публичном дизайне API я бы выбрал более явный путь.
источник
Нет, это, конечно, не обычная практика. Это нелогично, просто посмотреть на код, чтобы понять, что он делает, просто невозможно. Вы должны знать, как это используется, чтобы понять, как это используется.
Вместо предоставления атрибутов с использованием массива делегатов методы сцепления будут более понятными и будут работать лучше:
Хотя это немного больше, чтобы напечатать, это ясно и интуитивно понятно.
источник
.Attribute("style", "width:100%")
дает мнеstyle="width:100%"
, но, насколько я знаю, это может дать мнеfoooooo
. Я не вижу разницы.Могу ли я использовать это, чтобы написать фразу?
магическая лямбда (n): лямбда-функция, используемая исключительно для замены магической строки.
источник
Что не так со следующим:
источник
Все эти разговоры о "ужасности" - это куча давних ребят из c #, которые слишком остро реагируют (а я давний программист на C # и до сих пор очень большой поклонник языка). В этом синтаксисе нет ничего ужасного. Это просто попытка сделать синтаксис похожим на то, что вы пытаетесь выразить. Чем меньше «шума» в синтаксисе чего-либо, тем легче программисту это понять. Уменьшение шума в одной строке кода только немного помогает, но пусть это накапливается во все большем и большем количестве кода, и это оказывается существенным преимуществом.
Это попытка автора стремиться к тем же преимуществам, которые дает вам DSL - когда код просто «похож» на то, что вы пытаетесь сказать, вы достигли волшебного места. Вы можете обсудить, хорошо ли это для взаимодействия, или же оно более приятное, чем анонимные методы, чтобы оправдать некоторые затраты на «сложность». Достаточно справедливо ... поэтому в вашем проекте вы должны сделать правильный выбор, использовать ли этот тип синтаксиса. Но все же ... это умная попытка программиста сделать то, что в конце концов мы все пытаемся сделать (осознаем мы это или нет). И то, что мы все пытаемся сделать, это: «Скажите компьютеру, что мы хотим, чтобы он делал на языке, максимально приближенном к тому, как мы думаем о том, что мы хотим, чтобы он делал».
Становление ближе к тому, чтобы выразить наши инструкции компьютерам таким же образом, как мы думаем, является ключом к тому, чтобы сделать программное обеспечение более понятным и более точным.
РЕДАКТИРОВАТЬ: я сказал «ключ к созданию программного обеспечения более удобной и точной», что является наивно-завышенным преувеличением единорога. Я изменил его на «ключ».
источник
Это одно из преимуществ деревьев выражений - можно проверить сам код на наличие дополнительной информации. Таким
.Where(e => e.Name == "Jamie")
образом, можно преобразовать в эквивалентное предложение SQL Where. Это умное использование деревьев выражений, хотя я надеюсь, что оно не пойдет дальше этого. Что-то более сложное, вероятно, будет сложнее, чем код, который он надеется заменить, поэтому я подозреваю, что это будет самоограничением.источник
Это интересный подход. Если вы ограничите правую часть выражения только константами, то вы можете реализовать с помощью
Я думаю, что вы действительно хотите вместо делегата (вы используете лямбду, чтобы получить имена обеих сторон). См. Наивную реализацию ниже:
Это может даже решить проблему межязыкового взаимодействия, о которой упоминалось ранее в теме.
источник
Код очень умный, но потенциально он вызывает больше проблем, которые он решает.
Как вы указали, теперь существует неясная зависимость между именем параметра (стилем) и атрибутом HTML. Проверка времени компиляции не производится. Если имя параметра набрано неправильно, вероятно, на странице не будет сообщения об ошибке во время выполнения, но будет гораздо сложнее найти логическую ошибку (без ошибок, но некорректное поведение).
Лучшим решением было бы иметь элемент данных, который можно проверить во время компиляции. Итак, вместо этого:
код со свойством Style может быть проверен компилятором:
или даже:
Это большая работа для авторов кода, но этот подход использует преимущества сильной проверки типов в C #, которая в первую очередь помогает предотвратить попадание ошибок в код.
источник
на самом деле это похоже на Ruby =), по крайней мере для меня использование статического ресурса для более позднего динамического «поиска» не подходит для соображений проектирования API, надеюсь, что этот умный прием не является обязательным в этом API.
Мы могли бы наследовать от IDictionary (или нет) и предоставить индексатор, который ведет себя как массив php, когда вам не нужно добавлять ключ для установки значения. Это будет правильное использование семантики .net, а не только c #, и все еще нуждается в документации.
надеюсь это поможет
источник
На мой взгляд, это злоупотребление лямбдами.
Что касается блеска синтаксиса, то я нахожу это
style=>"width:100%"
довольно запутанным. Особенно из-за того, что=>
вместо=
источник
ИМХО, это классный способ сделать это. Мы все любим тот факт, что присвоение класса Controller сделает его контроллером в MVC, верно? Так что есть случаи, когда наименование имеет значение.
Также намерение здесь очень ясно. Это очень легко понять, что
.Attribute( book => "something")
приведетbook="something"
и.Attribute( log => "something")
приведет кlog="something"
Я думаю, это не должно быть проблемой, если вы относитесь к этому как к соглашению. Я считаю, что то, что заставляет вас писать меньше кода и делает намерение очевидным, - это хорошо.
источник
Если имена методов (функций) выбраны правильно, то это отличный способ избежать проблем с обслуживанием (т. Е. Добавить новую функцию, но забыл добавить ее в список отображения параметров функции). Конечно, вам нужно тщательно документировать это, и вам лучше будет автоматически сгенерировать документацию для параметров из документации для функций этого класса ...
источник
Я думаю, что это не лучше, чем "волшебные струны". Я не большой поклонник анонимных типов для этого. Это требует лучшего и строго типизированного подхода.
источник