public static TResult Return<TInput, TResult>(this TInput o, Func<TInput, TResult> evaluator)
where TInput : class
where TResult : class {
return o == null ? null :
evaluator == null ? null : evaluator(o);
}
Здравствуйте, Venom, Вы писали:
V>Пользуетесь ли таким и когда это может быть удобно?
Вчера писал ручной парсинг с Linq2Xml и заметил, что сабж удобен для доставания значений из XElement, если мы не знаем null ли он.
Например:
var value = xElement.Element("Smth").Value; // Possible NREvar value = xElement.Element("Smth").Return(x=>x.Value); // ok
И всё было хорошо, пока я не заметил, что стенку из
var value = xElement.Element("Smth").Return(x=>x.Value);
var value = xElement.Element("Smth").Return(x=>x.Value);
var value = xElement.Element("Smth").Return(x=>x.Value);
можно убрать, написав банальный метод ниже, и избавиться от лябмд:
public static DataParser {
public static XElement GetValue(XElement element, string childElementName){
var childElement = element.Element(childElementName);
return childElement == null ? null : childElement.Value;
}
}
От лямбд и от необходимости таких методов как Return.
Вот еще нашел у себя старый код, но такое уже антипаттерн и наркоманство :
Здравствуйте, Venom, Вы писали:
V>Суть в том, чтобы не городить проверки на null для доставания свойств объектов, если мы не знает является ли объект null или нет.
В C# 6 уже появился сахар для null propagation.
V>Пользуетесь ли таким и когда это может быть удобно?
Например, при возбуждении события:
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MyProperty)));
V>И всё было хорошо, пока я не заметил, что стенку из V>можно убрать, написав банальный метод ниже, и избавиться от лябмд
По-моему, вы сами ответили на свой вопрос, добавить особо нечего
Если в наследство досталась модель данных с цепочкой nullable свойств, то тут ничего не поделаешь: или ждать c#6, или писать свой хелпер для null propagation.
Если модель однотипная — эти хелперы быстро вытеснятся более специализированными, но и более удобными (в нашем проекте то же самое зовётся емнип TryGetElementValue/TryGetAttributeValue).
Префикс 'Try' важен. Иначе у вас будет два набора методов с однотипными названиями, но разным поведением: одни падают, другие возвращают null.
P.S. И да, монады тут ни к селу ни к городу. Вы ж не пишете про абелевы группы в одномерном линейном пространстве при обсуждении "x + y == y + x"?
Здравствуйте, Venom, Вы писали:
V>Здравствуйте, Venom, Вы писали:
V>>Пользуетесь ли таким и когда это может быть удобно?
V>Вчера писал ручной парсинг с Linq2Xml и заметил, что сабж удобен для доставания значений из XElement, если мы не знаем null ли он. V>Например: V>
V>var value = xElement.Element("Smth").Value; // Possible NRE
V>var value = xElement.Element("Smth").Return(x=>x.Value); // ok
V>
V>И всё было хорошо, пока я не заметил, что стенку из V>
V>var value = xElement.Element("Smth").Return(x=>x.Value);
V>var value = xElement.Element("Smth").Return(x=>x.Value);
V>var value = xElement.Element("Smth").Return(x=>x.Value);
V>
V>можно убрать, написав банальный метод ниже, и избавиться от лябмд:
Можно и нужно убрать. Метод а-ля Return нужен не для Value, а для Element.
Чтобы вместо
var el = doc.Element("el1");
if (el != null) el = el.Element("el2");
if (el != null) el = el.Element("el3");
return el != null ? el.Value : null;
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, Venom, Вы писали:
S>По-моему, вы сами ответили на свой вопрос, добавить особо нечего
Справедливости ради нужно отметить что это справедливо только для плоской модели как у меня.
В случае иерархии глубиной более трех, к сожалению возникнет потребность в таких "монадных" хелперах типа IfNotNull, как показал Jack128.
Кстати, у меня в другом проекте заводятся сущности (руками) для всех элементов, а значения хранятся в Attribute.Value, т.е. проблем с вложенностью не возникает, т.к. всегда работа идет на "плоском" уровне.
S>Если в наследство досталась модель данных с цепочкой nullable свойств, то тут ничего не поделаешь: или ждать c#6, или писать свой хелпер для null propagation.
Да, такая модель данных и досталась. Но имея только xml без схемы (кстати, не уверен, поможет ли она тут) по-другому модель и не опишешь, только через nullable свойства, потому что всегда может не оказаться какого-либо элемента/атрибута.
S>Если модель однотипная — эти хелперы быстро вытеснятся более специализированными, но и более удобными (в нашем проекте то же самое зовётся емнип TryGetElementValue/TryGetAttributeValue).
+1
S>Префикс 'Try' важен. Иначе у вас будет два набора методов с однотипными названиями, но разным поведением: одни падают, другие возвращают null.
+1
S>P.S. И да, монады тут ни к селу ни к городу. Вы ж не пишете про абелевы группы в одномерном линейном пространстве при обсуждении "x + y == y + x"?
+1
ЗЫ. > Ваш лимит оценок данному пользователю на сегодня исчерпан.
Первый раз достиг этого предела
Здравствуйте, Sinix, Вы писали:
S>Если модель однотипная — эти хелперы быстро вытеснятся более специализированными, но и более удобными (в нашем проекте то же самое зовётся емнип TryGetElementValue/TryGetAttributeValue). S>Префикс 'Try' важен. Иначе у вас будет два набора методов с однотипными названиями, но разным поведением: одни падают, другие возвращают null.
А не смущает, что префикс Try обычно применяется в методах a-la Try/Parse pattern? Сам для отличия от Get, которые всегда возвращают не-нулевое значение, применяю Find, то есть будет FindElementValue/FindAttributeValue. ИМХО, и симпотичнее (не двух-составной префикс, не путает с Try/Parse) и Find, как мне кажется, подразумевает, что результат может быть и не найден.
Здравствуйте, xy012111, Вы писали:
S>>Префикс 'Try' важен. Иначе у вас будет два набора методов с однотипными названиями, но разным поведением: одни падают, другие возвращают null. X>А не смущает, что префикс Try обычно применяется в методах a-la Try/Parse pattern?
Их явно отличает out-параметр и bool-результат. У неподготовленных разработчиков оба варианта никаких вопросов не вызывают, это главное.
X>Сам для отличия от Get, которые всегда возвращают не-нулевое значение, применяю Find, то есть будет FindElementValue/FindAttributeValue.
Этот вариант похуже на мой взгляд.
Во-первых, вгоняет в глубокий когнитивный диссонанс, если используются парные методы. Сравни GetSomething()/TryGetSomething() и GetSomething()/FindSomething(). Хотя Find() и без парных непонятен, т.к. практически нигде не используется.
Во-вторых, иногда Find не подходит, например,
var response = TrySendRequest(url)
Придумывать для подобных случаев частные случаи — прямой путь к абсолютно непонятному API.
Здравствуйте, Sinix, Вы писали:
S>>>Префикс 'Try' важен. Иначе у вас будет два набора методов с однотипными названиями, но разным поведением: одни падают, другие возвращают null. X>>А не смущает, что префикс Try обычно применяется в методах a-la Try/Parse pattern? S>Их явно отличает out-параметр и bool-результат. У неподготовленных разработчиков оба варианта никаких вопросов не вызывают, это главное.
В том-то и дело, что паттерн для Try методов есть. но ваш Try-метод в него не вписывается. Кажется, это не очень здорово для API, если можно сделать иначе.
X>>Сам для отличия от Get, которые всегда возвращают не-нулевое значение, применяю Find, то есть будет FindElementValue/FindAttributeValue. S>Этот вариант похуже на мой взгляд.
S>Во-первых, вгоняет в глубокий когнитивный диссонанс, если используются парные методы. Сравни GetSomething()/TryGetSomething() и GetSomething()/FindSomething().
А в чём диссонанс? "Получить" и "Найти" — вроде ясно всё, если минимумом языка владеть.
S>Хотя Find() и без парных непонятен, т.к. практически нигде не используется.
Если уж на то пошло, давайте сравним, где и как используется TryGet и Find И увидим, что именно ваш TryGet скорее подкованного человека введёт в диссонанс. Используется без out-параметра очень изредко, и в глубоких дебрях. А вот Find всегда одинаково и довольно-таки на поверхности.
S>Во-вторых, иногда Find не подходит, например,
S>var response = TrySendRequest(url)
Конечно тяжело говорить, не видя всего анамнеза, но мне кажется, что и такой Try здесь не фонтан. Например, SendRequest(url), всегда возвращающий некий response с кодом ошибки, который скажет о причине неудавшейся отправки может быть лучшим решением.
Вообще, речь шла о методах как раз об именовании методов поиска и Find там как нельзя кстати, как подсказывает здравый смысл и знание BCL.
S>Придумывать для подобных случаев частные случаи — прямой путь к абсолютно непонятному API.
Здравствуйте, Venom, Вы писали:
V>Здравствуйте, Sinix, Вы писали:
S>>Здравствуйте, Venom, Вы писали:
S>>По-моему, вы сами ответили на свой вопрос, добавить особо нечего
V>Справедливости ради нужно отметить что это справедливо только для плоской модели как у меня. V>В случае иерархии глубиной более трех, к сожалению возникнет потребность в таких "монадных" хелперах типа IfNotNull, как показал Jack128.
Ну, если нет возможности применить что-то типа XPath, а быстродействие — неважно, то можно сделать и более сложный хелпер, способный сократить цепочку Jack128 до
На основе, собсно, Expression Tree, в котором операторы "." переписываются в ".?".
S>>Если в наследство досталась модель данных с цепочкой nullable свойств, то тут ничего не поделаешь: или ждать c#6, или писать свой хелпер для null propagation. V>Да, такая модель данных и досталась. Но имея только xml без схемы (кстати, не уверен, поможет ли она тут) по-другому модель и не опишешь, только через nullable свойства, потому что всегда может не оказаться какого-либо элемента/атрибута.
C xml цепочками оперировать как раз легко — благодаря XPath.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, xy012111, Вы писали:
X>А в чём диссонанс? "Получить" и "Найти" — вроде ясно всё, если минимумом языка владеть.
По-моему, вариант Sinix немного лучше.
Вот почему:
В случае Get/Find не сразу видна их связь (один падает, другой возращает null).
В случае Get/TryGet эта связь видна и есть поверхностная ассоциация с Try/Parse паттерном, который работает схожим образом. И из-за этой поверхностной ассоциации такой вариант предпочтительнее в плане читабельности и интуитивности использования.
Здравствуйте, Venom, Вы писали:
V>В случае Get/TryGet эта связь видна и есть поверхностная ассоциация с Try/Parse паттерном, который работает схожим образом. И из-за этой поверхностной ассоциации такой вариант предпочтительнее в плане читабельности и интуитивности использования.
А ещё в MSVS почему-то никак не могут дойти со своими подсказками, что секция returns из xmldoc имеет значение, как раз для того что бы быстро обнаруживать подобную инфромацию (возвращается null или всё таки исключение). До смешного же доходит — summary показываем, аргументы — показываем (хотя часто как раз там и названий хватает), а возврат — нет.
PS: Да-да, я знаю, что взрослые расширения наподобии решарпера показывают.
Здравствуйте, fddima, Вы писали:
F> А ещё в MSVS почему-то никак не могут дойти со своими подсказками, что секция returns из xmldoc имеет значение, как раз для того что бы быстро обнаруживать подобную инфромацию (возвращается null или всё таки исключение). До смешного же доходит — summary показываем, аргументы — показываем (хотя часто как раз там и названий хватает), а возврат — нет.
F> PS: Да-да, я знаю, что взрослые расширения наподобии решарпера показывают.
Хм, у меня 7.0.1 решарпер. Суспенчу, не вижу разницы в тултипе MSVS между включенным и выключенным состояниями R#. Видимо, древноват он у меня.
Согласен, в тултипе MSVS было бы удобно видеть информацию из returns и из exceptions.
Здравствуйте, xy012111, Вы писали:
X>Здравствуйте, Sinix, Вы писали:
S>>>>Префикс 'Try' важен. Иначе у вас будет два набора методов с однотипными названиями, но разным поведением: одни падают, другие возвращают null. X>>>А не смущает, что префикс Try обычно применяется в методах a-la Try/Parse pattern? S>>Их явно отличает out-параметр и bool-результат. У неподготовленных разработчиков оба варианта никаких вопросов не вызывают, это главное.
X>В том-то и дело, что паттерн для Try методов есть. но ваш Try-метод в него не вписывается. Кажется, это не очень здорово для API, если можно сделать иначе.
Паттерн тут простой — попытаться сделать операцию без исключительных ситуаций. Какие там параметры и как они передаются — не важно.
Здравствуйте, Qbit86, Вы писали:
Q>Здравствуйте, Venom, Вы писали:
V>>Суть в том, чтобы не городить проверки на null для доставания свойств объектов, если мы не знает является ли объект null или нет.
Q>В C# 6 уже появился сахар для null propagation.
А почему Elvis? Типа задаём вопрос has Elvis left the building yet?
Здравствуйте, Vladek, Вы писали:
V>А почему Elvis?
«Since it first appeared in related languages, this has been known as the Elvis operator due to its resemblance to an emoticon... Groovy uses the '?:' operator, referred to as the "Elvis Operator" in the language documentation.»
Короче, графема ?. похожа на Элвиса (глаза и причёска).