Pull to refresh
29
Karma
0
Rating

Пользователь

  • Followers 41
  • Following 3

Упрощаем конвертеры для WPF

Похоже, для ваших целей может подойти встраиваемый конвертер (Inline Converter), который позволяет помещать лоику конвертирования в code-behaind на основе событийной модели.
Детали тут:
habr.com/ru/post/526450

Как воспоминания переживают ампутацию, метаморфозы, и передаются через инъекции

Ассоциативный ряд:
Хроники Акаши, пространство вариантов, мультивселенные, психоделика, сознательное и бессознательное, коллективное сознание, квантовая теория сознания, мозг как приёмник, смерть и рождение, трансформация, жизнь, любовь :)

Xакерский мерч | Мантия невидимка

Мантия неведимка

Или невИдимка? :)

В современных смартфонах предусмотрены функции авиарежима и отключения питания, а для полной анонимности можно оставить телефон дома! ;)

Вот для защиты от внешних электромагнитных импульсов экранирующий карман будет очень кстати.

typeof(T) vs. TypeOf⟨T⟩

Считайте всё это, чем захотите, я вам уже приводил своё определение паттерна раньше, и оно расходится с вашим, насколько мы выяснили. Поэтому нет ничего удивительного, что наши мнения снова отличаются.

typeof(T) vs. TypeOf⟨T⟩

На этом ваша аналогия и развалилась. Конкретная реализация паттерна не является паттерном.

Ничего не развалилось. Печально, если вы не улавливаете аналогию и не в состоянии ответить на последующие вопросы. Я сделал всё, что мог.

typeof(T) vs. TypeOf⟨T⟩

Я поправил
«Шарик — это собака (вид животных)»
на
«Шарик — это собака (животное)»

Чтобы было очевиднее, что
«Шарик — это животное»
«TypeOf⟨T⟩ — это паттерн»

Основной акцент в публикации делаю на TypeOf⟨T⟩, потому что дошёл до чёткого понимания этого паттерна лишь году на седьмом активного пользования дженериками. На мой взгляд, такое решение далеко не очевиденое, хотя довольно простое в своей основе.

Мемоизация или не мемоизация происходит в RipeType я не знаю, но кэширование точно есть и на новизну вовсе не претендую, основная цель была в проведении сравнительных бенчмарков.

typeof(T) vs. TypeOf⟨T⟩

Уже объяснял, но… TypeOf⟨T⟩ — конкретная реализация паттерна кэширования (мемоизации) через статический дженерик класс (назовём паттерн для дальнейшего примера Static Generic Memorization [SGM]), RipeType — через словарь (Dictionary Memorization [DM]).

Ровно так же, как StringBuilder — конкретная реализация паттерна Builder.

Рассмотрим простую аналогию. Названия видов животных (собака, кошка, бегемот, слон, дельфин...) соответствуют видам паттернам (SGM, DM, фабрика, билдер...). Конкретные реализации, например, Шарик и Мурка соответствуют конкретным реализациям TypeOf⟨T⟩ и RipeType.

Вместе с тем Шарик, являясь конкретной реализацией, не перестаёт быть собакой, как TypeOf⟨T⟩ не перестаёт быть реализацией паттена SGM.

Утверждения
«Шарик — это собака (животное)» являются истинными
«TypeOf⟨T⟩ — это SGM (паттерн)» тоже истинны.

Понятнее теперь?

typeof(T) vs. TypeOf⟨T⟩

можно его и под что-то еще адаптировать.
Именно. TypeOf, RipeType — конкретные случаи.

typeof(T) vs. TypeOf⟨T⟩

В первую очередь код ориентирован на десктопные и мобильные приложения.

typeof(T) vs. TypeOf⟨T⟩

Содержит, потому что я художник и так вижу.


А если серьёзно, каждый может по-своему откорректировать реализацию для продакшена, если потребуется, в публикации я только делюсь идеей (паттерном), а не идеальной имплементацией на все случаи жизни.

typeof(T) vs. TypeOf⟨T⟩

Да. А зачем вам описания?


  1. Clone All
  2. Find All по TypeOf

Конечно, зесь вам самим решать, тратить на это время или нет.

typeof(T) vs. TypeOf⟨T⟩

Как бы и разворачивает, но


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

https://msdn.microsoft.com/ru-ru/library/dd335949.aspx

typeof(T) vs. TypeOf⟨T⟩

Все мои случаи доступны в открытых репозиториях с кодом — изучайте при желании.

typeof(T) vs. TypeOf⟨T⟩

Из рубрики "Вредные советы" любителям антипаттернов


Использовать с осторожностью! Автор ответствености не несёт! :)


Global Lock
using System;

namespace Ace.Sugar
{
    public static class Lock<TResult>
    {
        public static readonly object GlobalSyncContext = new object();
    }

    public static class Lock
    {
        public static readonly object GlobalSyncContext = new object();

        public static void Invoke(Action action)
        {
            lock (GlobalSyncContext) action();
        }

        public static void Invoke<TSyncContext>(TSyncContext customSyncContext, Action<TSyncContext> action)
        {
            lock (customSyncContext) action(customSyncContext);
        }

        public static TResult Invoke<TResult>(Func<TResult> func)
        {
            lock (Lock<TResult>.GlobalSyncContext) return func();
        }

        public static TResult Invoke<TSyncContext, TResult>(TSyncContext customSyncContext, Func<TSyncContext, TResult> func)
        {
            lock (customSyncContext) return func(customSyncContext);
        }
    }
}

Минусы:


  • повышенная вероятность взаимной блокировки при использовании GlobalSyncContext
  • дополнительное выделение памяти при использовании лямбда выражений
  • плохая производительность в многопоточной среде

Плюсы:


  • не обязательно явно вводить новую переменную, позволяет ограничиваться однострочным кодом и использовать любимые лямбдочки везде и всюду, избегая ненавистных скобок { } в методах
  • не годится для продакшена, но для приложений на коленке сойдёт

Lock.Invoke(() => DoSomething());
Lock.Invoke(customSyncContext, c => DoSomething());

typeof(T) vs. TypeOf⟨T⟩

Да, везде заменил, потому что медленнее работать не будет в моих случаях, плюс общность появляется, а не где-то typeof, а где-то TypeOf.


А плата в виде слегка повышенное потребления памяти вполне для меня допустима.

typeof(T) vs. TypeOf⟨T⟩

Варианты оптимизаций я рассматриваю для каждого случая индивидуально. Касательно typeof у меня был ряд сценариев, где его избежать нельзя. Судя по результатам бенчмарков в терминах скорости выполнения, использование TypeOf в большинстве случаев даёт ощутимый выигрыш.


Есть потенциальный минус в виде статических объектов, постоянно находящихся в памяти, однако для моих приложений это допустимо.

typeof(T) vs. TypeOf⟨T⟩

Иногда по определённым вопросам спор с вами напоминает мне парадокс Кэррола.


Перед вами очевидные суждения:
А. чем меньше времени занимает событие, тем оно быстрее происходит
Б. определённые вызовы сравниваемых методов занимают меньше времени, чем другие


В. значит, эти вызовы быстрее


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

typeof(T) vs. TypeOf⟨T⟩

Для таких случаев есть служба поддержки в платёжной системе.


(: Шутка!

typeof(T) vs. TypeOf⟨T⟩

Да, текущая имплементация не лишена недостатков, но поскольку бенчмарки уже проведены на ней, в тексте публикации оставил её как есть, но добавил соответствующее примечание.


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

typeof(T) vs. TypeOf⟨T⟩

Короче, если в TypeOf<> на core избавиться от статического конструктора

Для меня это было сюрпризом, но инициализация статических полей выполняется вне/без статического конструктора.


Добавление явного статического конструктора в текущей имплементации TypeOf влияет на скорость доступа к статическим рид-онли полям, причём, есть зависимость от типа дженерик параметра — ссылочный он или нет. На CLR замедляет TypeOf⟨int⟩ и TypeOf⟨string⟩, но на Core ускоряет TypeOf⟨int⟩, оставляя производительность TypeOf⟨string⟩ на прежнем уровне.


Разница обусловлена кодом, генерируемым JIT-компилятором. В медленнных случаях при доступе к статическому рид-онли полю вставляется дополнительная инструкция для проверки того факта, проинициализировано оно уже или нет.


Вообще это связано с следующими вопросами:


  • Что выполняется раньше, инициализация полей либо статический конструктор?
  • Как гарантировать потокобезопасные инициализацию полей и вызов статического конструктора?

Сейчас в различных средах исполнения имеются свои тонкости в реализации этих механизмов.


Вашу оптимизацию можно использовать, если, к примеру, гарантировано вызывать TypeOf⟨A⟩.Init(), TypeOf⟨B⟩.Init()… при старте приложения, пока не создались другие потоки, использующие кэшированные данные. Поскольку вызовы одиночные большого проседания в скорости запуска приложения это не вызовет (можно также такие инициализации вынести в отдельный поток). К сожалению, это вносит неудобства в использование, но зато даёт дополнительный выигрыш в производительности для критичных случаев.

Information

Rating
Does not participate
Registered
Activity