Pull to refresh

Comments 41

В C# разве нет аналогов библиотек apache commons?
Я о таком не слышал. Может что есть?
Почитал про Apache Commons — понравилось.
UFO just landed and posted this here
Лично я буду благодарен за такую обёртку на регэксами. Удобно же.
А как с читабельностью?
Вопрос риторический.
UFO just landed and posted this here
Для того, чтобы совсем наверняка «порвал», можно RegexOptions.Compiled добавить.
А в остальном, да, конкретный, утрированный пример из статьи, данное регулярное выражение решает.

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

Если кому-то это тоже будет интересно — добро пожаловать. Остальные могут продолжать писать на асме использовать регулярные выражения.

А про быстродействие библиотеки, кстати, я даже нигде в статье не упоминал.
Забавно, но не думаю, что применимо в реальных проектах. Столько дополнительных классов ради того, что можно было бы сделать регулярками?
С точки зрения эстетики кода, весьма элегантно, но слишком нетипично для C#. Если метод Should() я еще могу понять, то перечислимый тип The
С каких пор текучие вызовы нетипичны для C#?) Очень даже в духе тенденций, так скажем.
Вызовы по цепочке как таковые — вполне типичны, а вот то, как они читаются — нет. В традициях C# было бы как-то типа такого:
var str = "some string";
var res = str.ToFluent()
             .Find("some", StringSearchDirection.FromEnd)
             .ReplaceWith("any", StringComparison.IgnoreCase);

А попытки сделать программный код правильным предложением на английском свойственны скорее DSL на Ruby.
А, в этом смысле да. Хотя, если посмотреть на мок- и модульно-тестовые библиотеки, там это вполне основной подход. Да и внутренние DSL на C# тоже вполне неплохо пишутся, например, когда предметная область из каких-нибудь тарифов по-разному собираемых — очень читаемо и красиво получается :)
Сам люблю велосипедостроение, но здесь-то чем регекспы не угодили?
UFO just landed and posted this here
Простите, что влезаю немного не в тему, но вот меня всегда поражало, как создатели .NET могли додуматься до названий вроде StringComparison.CurrentCultureIgnoreCase. Ведь это совершенно нечитабельно.
А как было бы читабельно?
Ну вот зачем сразу крайности (хотя в strcmpi не так всё и плохо). Посмотреть хотя бы на библиотеку Delphi, который был по сути прародителем .NET (и то, и другое ваял в том числе Андерс Хейлсберг). Там сделано из без extreme verbosity, и читаемо.
Так название конкретное предложите этому компаратору, как бы вы его назвали?
Дело не конкретно в этом компараторе, а в общем стиле именования, который предполагает имена в духе «НазваниеНеймспейсаИзДвадцатиБуквВCamelCase.ЧтоТоСлишкомДлинное». Как по мне, в отсутствие в языке (по понятным причинам) возможности передавать произвольные «незакавыченные» строки куда-либо неплохо было бы сделать своеобразный локальный неймспейсинг, чтобы default namespace для параметров функций мог меняться на тот, где они были объявлены, например. Ну или иной механизм похожего назначения. Потому как выглядит это совершенно уродливо и нечитаемо, что, собственно, и натолкнуло автора к написанию его библиотечки, кстати.
В значении StringComparison.CurrentCultureIgnoreCase нет неймспейса. Это enum и его значение через точку.

Вы предлагаете разрешить при вызове меотда принимающего enum (например StringComparison) не указывать тип enum'а?
А-ля «hello world».IndexOf(«w», CurrentCultureIgnoreCase)?
Ну хотя бы. Непонятно, почему все так радикально против, что даже в карму минусуют. Такое ощущение, что у присутствующих начисто отсутствуют какие-либо эстетические чувства.
Ну и помимо этого, как мне кажется, CurrentCulture само по себе излишне. Не уверен насчёт того, какие есть другие значения, но вроде как логичнее было бы указывать отличия от некоего «Current», чем каждый раз писать о его наличии.
Дело в том что StringComparison опционален. Есть перегрузки методов без него. Кроме CurrentCulture есть ещё InvariantCulture и Ordinal (это режим где сравнение идёт по charcode, не задумываясь о схожих символах в UTF).

Я с вами соглашусь про излишнюю многословность .NET. Но это его суть. Он создавался чтобы быть однозначным и простым в изучении (главным образом для индусов :)).

Т.е. конкретных предложений по конкретному примеру у вас нет?
string str = "Лев и медведь добыли мясо и стали за него драться. Медведь не хотел уступить, и лев не уступал."; var result = str.ReplaceAll("медведь").With("...").IgnoringCase();

Желание сделать что-то новое это похвально. Реализация — нет.

Я не готов посмотреть код на github (боюсь за психическое здоровье), но если бы меня заставили процитированный код саппортить, сделал бы такие выводы:
1. Extension метод Replace() создает какой-то промежуточный класс и туда пишет изначальную строку и слово «медведь»
2. метод With() либо создает еще один промежуточный класс, либо добавляет флаг в предыдущий
3. метод IgnoringCase(), не смотря на функциональную незначительность названия, является «спусковым ключком», который выполняет операцию замены и возвращает строку
4. Если в пунктах 1-3 нет промежуточного класса и данные хранятся в статических переменных, то автору надо отрубить руки
5. Если промежуточный класс есть, но пропустив IgnoringCase (или даже с ним) мы получаем в var result какой-то внутренний класс, а не строку, то автору надо отрубить руки
6. Если утверждения 4 и 5 не верны, а реализовано оно еще мудренее, то автору надо обязательно отрубить руки
Там везде возвращается внутренний класс с оператором неявной конвертации в строку. Не продолжайте, мы поняли, что нужно сделать с автором. =)
Fluent-интерфейсы возвращают ссылку на промежуточный объект (скорее всего всегда новый), постепенно добавляя туда разнообразные флажки. И данный объект имеет метод, разворачивающий флажки в то, что нам нужно. В данном случае, что очевидно, это будет ToString() и\или оператор перевода в строку.

Исходя из ваших утверждений, с подобным подходом вы не знакомы.
Почему же тогда вы позволили себе быть столь категоричным, даже не заглянув за ответами в код?
Еще в Java и AlertDialog.Builder я понял, что изобретателю этой «красивой» конструкции надо… ну вы поняли :)
Теперь буду знать, как это называется, спасибо!
Благо, в Java нет Extension methods и никто не наращивает так функционал базовых классов.
Да и в случае AlertDialog.Builder есть явный метод-триггер — там не додумались важный функционал на implicit type conversion привязывать :)

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

Потому как имею консервативное и устойчивое собственное мнение на счет подобных конструкций, вне зависимости от их dirty internals.
Да что там конструкция. Вы крайне негативно отозвались о реализации, сделав большое кол-во неверных утверждений, в то время как лежащий на поверхности правильный ответ вы явно проигнорировали. Ну банально нельзя так, невежливо.
ок, пристыдил. извиняюсь =)
Спасибо deilux за популярное описание внутреннего устройства Fluent интерфейсов. Я думал такое на Хабре объяснять не нужно.
В русле статьи будет

   My("Eyes").Are("Bleeding").Badly();
А теперь удалим все, учитывая регистр:

string t = "Строка ТЕСТ будет удалена с обоих концов ТЕСТ".RemoveAll("тЕСт").IgnoringCase();
t.Should().Be("Строка  будет удалена с обоих концов ");



Не пойму, ведь IgnoringCase означет «игнорить регистр», где ж тут учет того самого регистра?
Да, вы правы. Здесь должно быть "… без учета регистра".
Каждый программист должен написать библиотеку/обёртку для работы со строками)
Кстати говоря, с версии C# 4.0 он позволяет именовать аргументы при вызове. Можно сделать, например, такой метод, и будет ничуть не менее читаемо:\

var str = "hello world";
var res = str.Replace(
    from: "hello",
    to: "goodbye",
    ignoreCase: true
);
Sign up to leave a comment.

Articles