Комментарии 15
Сам FieldCache
использую в своем проекте (через NuGet). Не уверен, что кому-то нужен сам пакет, потому что гениального тут ничего нет, и, вероятно, проще написать свой велосипед.
Я использую эту штуку в своей библиотеке символьной алгебры, в которой такой паттерн чертовски полезен для математических выражений. Например, у математического выражения есть свойства InnerSimplified
, Evaled
, IsFinite
и прочие, которые необходимо кешировать, так как количество обращений к ним непредсказуемо.
Примеры: InnerSimplified, Evaled.
Тут вызываются рекурсивные методы, которые в общем случае должны были бы обходить все дерево выражения. В данном случае, при первом обращении к свойству, вычисления будут происходить основываясь на свойствах детей. К примеру, если мы хоть раз обратились к свойству Evaled
у выражения 2^5
, то при обращении к этому же свойству у выражения 2^5 + 3
у нас не будет заново вычисляться 2^5
. И это, по моему мнению, должно инкапсулироваться именно холдером, чтобы при обращении к свойству ни о чем думать не нужно было, и считать это обращение — бесплатным.
Это и есть ленивая инициализация. Но так как у нас неизменяемые объекты, то и сами закешированные значения никогда не станут неверными
Смотрите, может быть кейс когда их много и когда одно свойство ссылается на пару других. Ваш подход поощряет стиль написания кода, который может привести к такой ситуации.
Как тогда искать начало и конец инициализации?
Смотрите, может быть кейс когда их много и когда одно свойство ссылается на пару других. Ваш подход поощряет стиль написания кода, который может привести к такой ситуации.
Да, верно. А вот что значит "искать начало и конец инициализации" — не очень понятно. Если вы хотите что-то отдебажить, достаточно изолировать ваш объект от других, и при первом обращении попадете туда, куда нужно. Хотя можно и проще: поставить условные бряки и когда-нибудь ваш метод вызывется.
Может лучше было и обертку, я просто писал о наивной реализации. Может еще смогу добить его по скорости, но задача все-таки была не в этом, а поделиться идеей дизайна
я перефразирую, не делайте плз так в продакшн коде, это плохая идея, по этим граблям рано или поздно ходит каждый разработчик на С#
смотрите в сторону отдельных функций это даст вам больше степеней свободы:
как их компоновать и где и как долго хранить результаты
это другая ответственность
PS я просто оставлю это тут
https://github.com/Aaronontheweb/FastAtomicLazy/tree/master/FastAtomicLazy
Вы можете сказать, в чем грабли?
Сейчас я использую это в библиотеке. Вместо того, что бы думать, где запускать Eval(), а где нет, а где один раз запустить, я просто обращаюсь к одному свойству. Это сильно увеличило скорость разработки и производительность (потому что все результаты все время кешируются).
А ваших аргументов я пока не услышал.
вот пример, не увернен насчет рекордов
https://codereview.stackexchange.com/questions/129081/property-caching
но как вы думаете почему после изобретения всех подходов для CachedProperty
автор вопроса всеравно пришел к стандартному?
Lazy<int> LazyMul;
public override int Mul => LazyMul.Value;
Я уже говорил, почему приватное поле с Lazy
я не могу позволить себе. И я же в итоге делаю что-то похожее, просто лишенное недостатков классического подхода.
И на всякий случай скажу: меня верно подправили выше, это скорее ленивая инициализация, а не кеш, потому что в ленивой инициализации не надо ничего инвалидировать (в отличии от топика, что вы кинули).
lock (@this)
если у вас тип неизменяемый?Ну вызовет кто-то его два раза, в худшем случае где-то будет «нетот» трипл. Но у него будет тот же hash и то же value что и «правильного» трипла — не вижу в чем проблема (а зато выигрыш в скорости без лока и второй проверки можете сами прикинуть)
Методы без аргументов — зло в ООП, и вот как его полечить