Полезняшка для dictionary
От: -n1l-  
Дата: 29.04.16 14:48
Оценка:
    public static TResult GetValue<TKey, TValue, TResult>(this IDictionary<TKey, TValue> source, 
                                                          TKey key, 
                                                          Func<TValue, TResult> callback,
                                                          Func<TKey, TResult> callbackIfEmpty)
    {
      if (!source.ContainsKey(key))
      {
        return callbackIfEmpty(key);
      }
      var result = source[key];

      return callback(result);
    }


Как вам такое?
Re: Полезняшка для dictionary
От: IT Россия linq2db.com
Дата: 29.04.16 15:00
Оценка:
Здравствуйте, -n1l-, Вы писали:

N>Как вам такое?


Почему не через TryGetValue?
Если нам не помогут, то мы тоже никого не пощадим.
Re: Полезняшка для dictionary
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 29.04.16 15:22
Оценка:
Здравствуйте, -n1l-, Вы писали:

N>Как вам такое?


Присутствует под названием GetValueOrDefault. Или я что то не так понял?
[Pure]
public static TResult GetValueOrDefault<TKey, TValue, TResult>(
    [NotNull] this IDictionary<TKey, TValue> dictionary,
    TKey key,
    [NotNull, InstantHandle] Func<TKey, TValue, TResult> resultSelector,
    [NotNull, InstantHandle] Func<TKey, TResult> defaultValueFactory)
{
    Code.NotNull(dictionary, nameof(dictionary));
    Code.NotNull(resultSelector, nameof(resultSelector));
    Code.NotNull(defaultValueFactory, nameof(defaultValueFactory));

    TValue result;
    return
        dictionary.TryGetValue(key, out result)
            ? resultSelector(key, result)
            : defaultValueFactory(key);
}
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Отредактировано 29.04.2016 15:23 AndrewVK . Предыдущая версия .
Re[2]: Полезняшка для dictionary
От: -n1l-  
Дата: 29.04.16 16:51
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, -n1l-, Вы писали:


N>>Как вам такое?


AVK>Присутствует под названием GetValueOrDefault. Или я что то не так понял?

AVK>
AVK>[Pure]
AVK>public static TResult GetValueOrDefault<TKey, TValue, TResult>(
AVK>    [NotNull] this IDictionary<TKey, TValue> dictionary,
AVK>    TKey key,
AVK>    [NotNull, InstantHandle] Func<TKey, TValue, TResult> resultSelector,
AVK>    [NotNull, InstantHandle] Func<TKey, TResult> defaultValueFactory)
AVK>{
AVK>    Code.NotNull(dictionary, nameof(dictionary));
AVK>    Code.NotNull(resultSelector, nameof(resultSelector));
AVK>    Code.NotNull(defaultValueFactory, nameof(defaultValueFactory));

AVK>    TValue result;
AVK>    return
AVK>        dictionary.TryGetValue(key, out result)
AVK>            ? resultSelector(key, result)
AVK>            : defaultValueFactory(key);
AVK>}
AVK>


А я не смотрел код)
Только сегодня додумался о такой функции и решил предложить.
А почему у первого колбэка два параметра входных?
Зачем?
Re[2]: Полезняшка для dictionary
От: -n1l-  
Дата: 29.04.16 16:52
Оценка:
Только сегодня идея пришла в голову.
Re[3]: Полезняшка для dictionary
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 29.04.16 16:59
Оценка:
Здравствуйте, -n1l-, Вы писали:

N>А почему у первого колбэка два параметра входных?

N>Зачем?

Иногда бывает нужно.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[4]: Полезняшка для dictionary
От: -n1l-  
Дата: 29.04.16 17:06
Оценка:
Сразу до кучи — ForEach для IEnumerable запилили?
Re[5]: Полезняшка для dictionary
От: Jack128  
Дата: 29.04.16 17:56
Оценка:
Здравствуйте, -n1l-, Вы писали:

N>Сразу до кучи — ForEach для IEnumerable запилили?

Не нужен. А вот
IEnumerable<T> Do(this IEnumerable<T> source, Action<T> action)

был бы полезен
Re[6]: Полезняшка для dictionary
От: Sinix  
Дата: 29.04.16 18:11
Оценка:
Здравствуйте, Jack128, Вы писали:

J>Не нужен. А вот

IEnumerable<T> Do(this IEnumerable<T> source, Action<T> action)

J> был бы полезен
Оба не нужны.
Серьёзно, давайте всё-таки предлагать фичи по принципу "есть _реальный_ сценарий использования", а не "что б ещё такое переподвывернуть?"

Для последнего php с js есть, развлекайся — не хочу

Есть сценарий — не вопрос, можно обсудить. Нет — я бы выкидывал без сожалений. Мы ж не за количеством методов гонимся
Re[5]: Полезняшка для dictionary
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 29.04.16 19:38
Оценка: +1
Здравствуйте, -n1l-, Вы писали:

N>Сразу до кучи — ForEach для IEnumerable запилили?


Нет и не будет. Ибо зло в чистом виде
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[6]: Полезняшка для dictionary
От: -n1l-  
Дата: 30.04.16 09:38
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, -n1l-, Вы писали:


N>>Сразу до кучи — ForEach для IEnumerable запилили?


AVK>Нет и не будет. Ибо зло в чистом виде


почему?
Re[6]: Полезняшка для dictionary
От: -n1l-  
Дата: 30.04.16 09:39
Оценка:
В чем разница?
Re[7]: Полезняшка для dictionary
От: -n1l-  
Дата: 30.04.16 09:41
Оценка:
Ну я запилил себе ForEach для IEnumerable, нарадоваться не могу.
Re[7]: Полезняшка для dictionary
От: Jack128  
Дата: 30.04.16 11:39
Оценка:
Здравствуйте, -n1l-, Вы писали:


N>В чем разница?


в возвращаемом значении.
простой ForEach ничем от цикла не отличается. Кроме производительности


А вот чтоб переписать код ниже без метода Do — нужно заводить отдельный метод

IEnumerable<MyObj> GetObjs()  {  .... } // получаем данные
void Process(IEnumerable<MyObj> objs) // обрабатываем их как то
{
   foreach(var obj in objs)
   {
      ...      
   }
}
AdditionalData GetAdditionalData(MyObj obj) { ... } 

Proccess(GetObjs().Do(obj => obj.AdditionalData = GetAdditionalData(obj)));
Отредактировано 30.04.2016 11:44 Jack128 . Предыдущая версия . Еще …
Отредактировано 30.04.2016 11:43 Jack128 . Предыдущая версия .
Re[7]: Полезняшка для dictionary
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 30.04.16 13:33
Оценка: +1
Здравствуйте, -n1l-, Вы писали:

AVK>>Нет и не будет. Ибо зло в чистом виде

N>почему?

Потому что при чтении кода linq выражения человеком обычно воспринимаются как pure. И если на самом деле там внутри меняется внешнее состояние, это сильно снижает читаемость кода. Что есть зло.
А в зло в чистом виде, потому что никакого преимущества такой метод по сравнению с оператором foreach не дает, только лишний синтаксический шум и маскировка под чистые методы.
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[8]: Полезняшка для dictionary
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 30.04.16 13:41
Оценка: +1
Здравствуйте, Jack128, Вы писали:

J>А вот чтоб переписать код ниже без метода Do — нужно заводить отдельный метод

J>
J>IEnumerable<MyObj> GetObjs()  {  .... } // получаем данные
J>void Process(IEnumerable<MyObj> objs) // обрабатываем их как то
J>{
J>   foreach(var obj in objs)
J>   {
J>      ...      
J>   }
J>}
J>AdditionalData GetAdditionalData(MyObj obj) { ... } 

J>Proccess(GetObjs().Do(obj => obj.AdditionalData = GetAdditionalData(obj)));
J>


AdditionalData GetAdditionalData(MyObj obj) { ... }

foreach (var obj in GetObjs())
{
    obj.AdditionalData = GetAdditionalData(obj)
    Process(obj);
}

Короче и понятнее. Или я чего то не понял?

Непременно надо цикл в метод запихнуть?
void Process(IEnumerable<MyObj> objs, Action<MyObj> preprocessor) // обрабатываем их как то
{
   foreach(var obj in objs)
   {
      preprocessor(obj);
      ...      
   }
}


Ну или если совсем уж намеренно упороться, то:
Proccess(GetObjs().Select(obj => {obj.AdditionalData = GetAdditionalData(obj); return obj;}));
... << RSDN@Home 1.0.0 alpha 5 rev. 0 on Windows 8 6.2.9200.0>>
AVK Blog
Re[8]: Полезняшка для dictionary
От: -n1l-  
Дата: 30.04.16 14:47
Оценка:
Здравствуйте, AndrewVK, Вы писали:

Как вы поступаете с большими выражениями?
Создаете временную переменную?
И что так лучше читается вместо добавления одного метода, который этот форыч инкапсулирует?
Re[8]: Полезняшка для dictionary
От: Sinix  
Дата: 30.04.16 15:27
Оценка:
Здравствуйте, Jack128, Вы писали:

J>А вот чтоб переписать код ниже без метода Do — нужно заводить отдельный метод

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

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

Серьёзно, это прям таки классический пример, почему код нельзя писать в solution-driven стиле.
Допустим, Process чуть позже станет фильтровать objs или получать только последний из них. Соответственно, большая часть AdditionalData будет заполнена зря.
Зашибись как сэкономили, да?

Вы точно уверены, что хотите поддерживать код с такими потенциальными багами?

Ну и как всегда правильный варинт:
1. признать, что текущий дизайн — отстой, т.к. вынуждает лепить костыли в самых тривиальных случаях.
2. Сделать рефакторинг под реальный сценарий использования. Например, вытащить тело цикла в отдельный метод.
3. В будущем на code review показывать разработчику, что в 99% случаев необходимость в костылях к стандартным конструкциям языка означает криво спроектированное API. Правильный способ — не прикрыть текущую ситуацию штукатуркой, а чинить исходную проблему.
Re[9]: Полезняшка для dictionary
От: -n1l-  
Дата: 30.04.16 16:09
Оценка:
Здравствуйте, Sinix, Вы писали:
S>3. В будущем на code review показывать разработчику, что в 99% случаев необходимость в костылях к стандартным конструкциям языка означает криво спроектированное API. Правильный способ — не прикрыть текущую ситуацию штукатуркой, а чинить исходную проблему.

Это в мирках где бизнес-логика настолько простая, что все что нужно делать — использовать стандартные методы фреймворка?
Re[10]: Полезняшка для dictionary
От: Sinix  
Дата: 30.04.16 17:17
Оценка:
Здравствуйте, -n1l-, Вы писали:

S>>3. В будущем на code review показывать разработчику, что в 99% случаев необходимость в костылях к стандартным конструкциям языка означает криво спроектированное API. Правильный способ — не прикрыть текущую ситуацию штукатуркой, а чинить исходную проблему.


N>Это в мирках где бизнес-логика настолько простая, что все что нужно делать — использовать стандартные методы фреймворка?

Э-э-э, пост внимательней читай
речь была про

необходимость в костылях к стандартным конструкциям языка

,
не про хелперы для фреймворка.

Предложенный Do() означает, что девелоперу влом написать foreach. Или что дизайн API вынуждает вырезать гланды с другой стороны, как в примере с GetAdditionalData().


И таки да, костяк БЛ практически никогда не вылезает за if/else/foreach + хелперы для "on A,B,C changed — do Y", всё страшное прячется на уровень ниже, в методы, которые разруливают конкретные случаи. Точнее, оно так может быть записано. А на практике я видел всё — от кодогенерации конечных автоматов в рантайма и до логики в 5-6 килострок на linq. Но это не значит, что код надо писать так

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