Pull to refresh
8
0
Толмачёв Дмитрий @FiresShadow

Разработчик ПО

Send message
По поводу оптимизации я уже высказывался в этом комментарии.
И в этом случае слабые ссылки не помогут никак.

Не помогут в чём? Утечки памяти возникнут? Если объект не уничтожен, сборщиком мусора его собирать не надо.
Видите ли, публичный контракт ObservableCollection не гарантирует, что Reset вызывается только при Clear
Немного вас подправлю, а то вдруг кто-то прочитает и подумает, что правда не требует. На самом деле требует, но в старых версиях .NET Framework (до 4.5) не требовал.
Никто не говорил про сырость, речь шла про надёжность и известность. Кстати, первый коммит был сделан примерно 3 года назад, 7 июля 2012.

Давайте представим, какие сложности могут возникнуть при использовании этой библиотеки.
1)Имена свойств передаются в атрибуты через строки, что вызывает сложности при навигации и переименовании: в параметры атрибутов можно передавать только константы, и код, вычисляющий имя свойства, задействовать не удастся.
2)По слова пользователей, Fody не поддерживает обработку вложенных коллекций. Если возникнет такая необходимость, то можно: а)написать разработчикам Fody и ждать у моря погоды (но станет ли ждать заказчик?) б)использовать другой менеджер зависимостей в)использовать код из этой статьи.

как увеличивается производительность, так и уменьшается размер приложения

Ну давайте посмотрим, насколько отличается код. В случае Fody мы непосредственно вызываем два RaisePropertyChanged, а в случае кода из статьи — вызываем один RaisePropertyChanged, а второй вызывается как подписчик. Насколько команд процессора во втором случае больше? На одного подписчика больше, значит на одну итерацию цикла больше, примерно 7 команд: инкрементация счётчика цикла, проверка на выход из цикла, переход на нужную инструкцию, 4 операции вызова метода (вычисление адреса метода по объекту и смещению, переход, копирование регистров процессора 2 раза). Поскольку это происходит не в режиме ядра, то возможно ОС выполнит какие-то действия. Грубо говоря, пусть будет с запасом 20 операций. Сколько там у вас в ViewModel обычно вычислимых свойств? А чего мелочится, пусть будет 20. Большая такая ViewModel. И допустим отображаете вы не одно поле, а целую таблицу из 100 элементов, на большом таком мониторе. Итого 40000 операций. Допустим пользователь пользуется программой на смартфоне с процессором в 1 ГГц. Итого пользователь будет ждать аж на целых 0,00004 секунды больше! Бедный пользователь. Мне почти стыдно. Уже бегу усложнять процесс сборки и отладки солюшена, чтобы страдал я и мои коллеги, а не пользователь. Шучу. Коллег жалко. И кстати, я не против Fody, я против экономии на спичках.
Не знал, спасибо. Ну тогда придётся заменить

if (args.Action == NotifyCollectionChangedAction.Add || args.Action == NotifyCollectionChangedAction.Replace)

на

if (args.NewItems != null && args.NewItems.Any()).

Сделал из этого некоторые выводы. Благодарствую, удалось извлечь пользу из диалога с вами :)
это утечки

Если честно, уже не смешно. Я потерял счёт, сколько раз я вам говорил про утечки памяти и слабые события. Ваш троллинг слишком толст.

Конечно, типовая ObservableCollection делает Reset только при Clear, только любой шаг вправо или влево сделает ваш код неработоспособным.
Ага, а давайте рассмотрим ещё пример: типовой List<> добавляет во время Add() ровно один элемент, а если сделать в наследнике чтобы Add добавляло сам элемент и его копию, то какой-нибудь код, рассчитывающий что после Add() Count увеличивается ровно на единицу, станет неработоспособным. Можно сделать почти любой код неработоспособным, пренебрегая элементарными правилами наследования. Почитайте про принцип Лисков.
Подчеркнул нужное место…

collection.CollectionChanged += (sender, args) =>
{
RaisePropertyChanged(propertyName);

if (args.Action == NotifyCollectionChangedAction.Add || args.Action == NotifyCollectionChangedAction.Replace)
{
foreach (var addedItem in args.NewItems)
{
RegisterElementPropertyDependencies(propertyName, addedItem, destinationPropertyNames, actionOnChanged);
}
}
};
Вы во всех ветках будете писать, что не видите в коде слабых событий? Ответил вам в другой ветке.
Подчеркнул это место.

collection.CollectionChanged += (sender, args) =>
{
RaisePropertyChanged(propertyName);

if (args.Action == NotifyCollectionChangedAction.Add || args.Action == NotifyCollectionChangedAction.Replace)
{
foreach (var addedItem in args.NewItems)
{
RegisterElementPropertyDependencies(propertyName, addedItem, destinationPropertyNames, actionOnChanged);
}
}
};
Описание слабых ссылок
Описание слабых событий
Нет, слабых событий на данный момент в коде нет. Почему нет, я вам говорил ранее — чтобы не перегружать пример кода:
Пример кода отражает основной смысл, который в него заложен (имхо, такими и должны быть примеры — краткими и конкретными). Чтобы память не текла, используйте слабые ссылки. Это, на мой взгляд, best practise при практически любом использовании событий.

Подумаю, может быть, добавлю в статью код примера слабых событий. Хотя не вижу особого смысла. В сети наверняка есть примеры, как это делается, я тут ничего нового не скажу.
Я же лично вам недавно говорил про утечки памяти и слабые ссылки.
предпочитаю своевременную отписку
Т.е. вы предлагаете добавить метод Dispose, в котором будет происходить отписка, и возложить на плечи программиста\архитектуры дополнительную ответственность?
В коллекции обрабатывается только добавление элемента. А как же остальные 4 действия — Remove, Move, Replace и Reset?
Неправда, посмотрите код ещё раз.
Что касается слабых ссылок, то, это, по моему, вообще из пушки по воробьям.

Вы знаете более простой и надёжный способ? В чём он заключается?
Результат этого понятен: изменения в объектах, которые уже нашей цепочки не принадлежат, будут инициировать уведомления об изменении цепочки, что неверно.


Можно сделать отписку при удалении элемента из коллекции, а можно и не делать. Сам по себе случай, когда элемент изымается из отображения, и после этого с ним производятся какие-то действия, довольно редок. Обычно, если элемент перестаёт отображаться, значит он пользователя больше не интересует, и никаких действий с ним не планируется. Но что будет, если такой случай всё же произойдёт? В View перерисуется элемент, зависящий от вычислимого свойства в ViewModel, который мог не перерисовываться. Опять таки, а много у вас вычислимых свойств в проекте, и насколько они сложные? Не вижу необходимости делать преждевременную оптимизацию, усложняя код, чтобы в каких-то очень экзотических ситуациях он отрабатывал на несколько миллисекунд быстрее.
Хотя если у вас в проекте такие случаи встречаются, то можете и задуматься об оптимизации. Хотя раз в данном случае оптимизация будет заключаться в каких-то дополнительных действиях, то в одних местах код будет работать быстрее, а в других — медленнее. Тут лучше на конкретном проекте смотреть, сколько микросекунд мы выиграем, сколько потеряем, и стоит ли усложнение кода выигранного быстродействия.
Тут нужно смотреть на известность и надёжность стороннего проекта, а также на развивающее его сообщество. Я про конкретно этот проект впервые слышу, так что не могу дать свою оценку. Если вы уверены, что с проектом проблем не возникнет и вам не придётся объяснять новому человеку на проекте, как им пользоваться, то бога ради, используйте. Если такой уверенности нету, то можете использовать мои два небольших метода. Поскольку методы небольшие и в них несложно разобраться, то 1)новый человек на проекте наверняка разберётся, увидев пример и исходный код 2)в случае чего можно будет легко отладить код и найти проблему — как в клиентском коде, так и в коде этих методов.
В любом случае, теперь вы знаете ещё один способ реализации binding-а вычислимых свойств в WPF.
Сами методы не слишком простенькие, а код регистрации совсем не простенький.
Это субъективно. Вот что объективно: в приведенном мной примере 2 небольших метода, в указанном вами проекте множество немаленьких классов. Не знаю сколько из них занимаются непосредственно управлением зависимостями, но в любом случае, раз там всё построено на изменении кода в момент компиляции, то кода наберётся немало.

одна подписка на событие без отписки уже намекает
Пример кода отражает основной смысл, который в него заложен (имхо, такими и должны быть примеры — краткими и конкретными). Чтобы память не текла, используйте слабые ссылки. Это, на мой взгляд, best practise при практически любом использовании событий.

Объем демо и объяснений в вашем случае требуется не меньший
Небольшое summary и сам код — вот лучшее объяснение. Пример использования — вот лучшее демо (вы же не будете копировать эти методы в свой проект, если не собираетесь их сразу же использовать, верно?).

Отлаживать его вроде как тяжелее, зато сама отладка потребуется куда реже.
На основании чего вы делаете такие выводы? Похоже на гадание на кофейной гуще — что и сколько раз потребуется отлаживать. Да, там 10 контрибьюторов, но сам проект объективно сложнее устроен. Отлаживать сторонний большой проект сложнее, чем два небольших метода — с этим согласен.
Да, менеджеров зависимостей довольно много. Но я бы предпочёл иметь дело с двумя простенькими методами, чем со сторонним проектом, делающим тоже самое. Во-первых, если придёт новый человек, который с этим сторонним проектом не работал, то придётся ему показывать, что да как. Ну или он сам потратит время, чтобы почитать мануалы или разобраться интуитивно. Или если в проекте есть ошибка, например он некорректно обрабатывает вложенные коллекции, то потребуется больше времени, чтобы понять, что ошибка в чёрном ящике, а не в собственном коде. А когда работаешь с двумя простенькими методами, у которых есть summary, то сразу видно 1)как это работает и 2)где ошибка.
Ответил в виде статьи — вдруг кому-то ещё будет интересно посмотреть. Код писал примерно час-полтора.

Information

Rating
Does not participate
Location
Россия
Date of birth
Registered
Activity