Как я убеждаю своих коллег не реализовывать IDisposable на всем? [закрытый]

Нет - статическая инициализация эти instance будет только когда-либо делаться однажды. Две вещи рассмотреть:

  • Это не ориентировано на многопотоковое исполнение (экземпляр не "публикуется" к оперативной памяти)
  • Ваш firstTime, метод, вероятно, называют многократно, если правильно не синхронизируется
18
задан Brian Rasmussen 18 August 2010 в 18:10
поделиться

10 ответов

По совпадению я только что разместил этот комментарий в другом месте:

Ссылка на объект, являющийся неправильно сохраненный все еще утечка ресурсов. Вот почему программы GC все еще могут быть утечки, обычно из-за паттерн Наблюдатель - наблюдатель есть в списке вместо наблюдаемых и никогда не снимается. В конечном итоге удалить необходимо для каждого добавить , просто поскольку удаление необходимо для каждого нового . Точно такая же ошибка программирования, вызывая точно такую ​​же проблему. А "ресурс" на самом деле всего лишь пара функции, которые должны называться равное количество раз с соответствующие аргументы, а "утечка ресурсов" - это то, что происходит, когда вы не можете этого сделать.

И вы говорите:

цель IDisposable - освободить любой Неуправляемые ресурсы ваши объекты control

Теперь операторы + = и - = для события фактически представляют собой пару функций, которые вы должны вызывать равное количество раз с соответствующими аргументами (событие / обработчик, являющийся соответствующими аргументами).

Следовательно, они составляют ресурс. А поскольку сборщик мусора не обрабатывает их (и не «управляет» ими), может быть полезно думать о них как о еще одном виде неуправляемых ресурсов. Как указывает Джон Скит в комментариях, «неуправляемый» обычно имеет особое значение, но в контексте IDisposable я думаю, что полезно расширить его, включив в него что-нибудь вроде ресурсов, которое нужно «снести» после он был «построен».

Таким образом, отсоединение событий - очень хороший кандидат для обработки с помощью IDisposable .

Конечно, вам нужно где-то вызвать Dispose , и вам не нужно его реализовывать на каждом отдельном объекте (только на тех, у которых есть отношения событий, которые требуют управления).

Также имейте в виду, что если пара объектов связана событием, и вы «бросаете их по течению», теряя все ссылки на них в все остальные объекты не поддерживают друг друга в живых. GC не использует подсчет ссылок. Как только объект (или остров объектов) становится недоступным, он может быть собран.

Вам нужно только беспокоиться об объектах, перечисленных в качестве обработчиков событий с событиями на объектах, которые существуют долгое время. например, статическое событие, такое как AppDomain.UnhandledException , или события в вашем приложении »

16
ответ дан 30 November 2019 в 06:35
поделиться

Укажите на Joe Duffy's сообщение об IDisposable / finalizers - объединенная мудрость многих умных людей.

В настоящее время мне трудно увидеть там утверждение, в котором говорится: «Не внедряйте это, когда оно вам не нужно» - но помимо что-нибудь еще, показав им сложность его правильной реализации, вполне может помочь отговорить их от этого ...

К сожалению, если люди не будут слушать, они не будут слушать. Попытайтесь заставить их объяснить , почему они думают, что им нужен IDisposable . Они думают, что сборщик мусора не работает? Покажите им, что это работает. Если вы сможете убедить их, что это не приносит пользы (для большинства типов), тогда они наверняка перестанут добавлять работу для себя ...

Как говорит Брайан, реализация IDisposable не поможет с проблема события сама по себе - она ​​должна быть чем-то вызвана . Финализаторы и в этом вам не помогут. Им действительно нужно явно сделать что-то , чтобы удалить обработчики событий.

Они думают, что сборщик мусора не работает? Покажите им, что это работает. Если вы сможете убедить их, что это не приносит пользы (для большинства типов), тогда они наверняка перестанут добавлять работу для себя ...

Как говорит Брайан, реализация IDisposable не поможет с проблема события сама по себе - она ​​должна быть чем-то вызвана . Финализаторы и в этом вам не помогут. Им действительно нужно явно сделать что-то , чтобы удалить обработчики событий.

Они думают, что сборщик мусора не работает? Покажите им, что это работает. Если вы сможете убедить их, что это не приносит пользы (для большинства типов), тогда они наверняка перестанут добавлять работу для себя ...

Как говорит Брайан, реализация IDisposable не поможет с проблема события сама по себе - она ​​должна быть чем-то вызвана . Финализаторы и в этом вам не помогут. Им действительно нужно явно сделать что-то , чтобы удалить обработчики событий.

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

Это само по себе не поможет решить проблему с событием - оно должно быть чем-то вызвано . Финализаторы и в этом вам не помогут. Им действительно нужно явно сделать что-то , чтобы удалить обработчики событий.

11
ответ дан 30 November 2019 в 06:35
поделиться

Простая реализация Dispose () для всех типов не решит вашу проблему. Помните, что Dispose () не вызывается автоматически, и он не имеет ничего общего с освобождением управляемой памяти. Чтобы получить какой-либо эффект от ваших методов Dispose () , вам необходимо вызвать их во всех соответствующих местах - либо явно, либо через с использованием .

Другими словами, простая реализация IDisposable не решит ваши проблемы волшебным образом, потому что методы Dispose () не будут вызываться, если вы также не измените использование каждого типа в вашем код.

Однако я бы не рекомендовал реализовать IDisposable для всех ваших типов просто потому, что это не имеет смысла. Интерфейс используется, чтобы указать, что рассматриваемый тип использует некоторый ресурс, который не обрабатывается сборщиком мусора.

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

9
ответ дан 30 November 2019 в 06:35
поделиться

Однажды я помог коллеге решить аналогичную проблему с возникновением ошибок OutOfMemoryException (вызванных событиями, которые оставляют ссылки на объекты висящими вокруг). Первое, что я сделал, это запустил код через FXCop, который выделил Dispose не вызывался в классе IDisposable.

Изменение этого кода для удаления устранило проблему. Возможно, вам стоит порекомендовать использовать FXCop?

Возможно, найдите код с проблемой в исходном репозитории, запустите на нем FXCop - посмотрите, выделяет ли он проблему (вероятно, будет, если она вызвана классом .NET Framework) и используйте это, чтобы убедить своих коллег.

5
ответ дан 30 November 2019 в 06:35
поделиться

Это сложно осуществить, но я нашел, что лучший способ заставить людей делать то, что вы хотите, - это позволить им думать, что это их идея. Вы знаете их лучше, чем я, но такие фразы, как «Если бы только был способ узнать, почему объекты так долго торчат» и «Хотел бы я знать больше о событиях, связанных с объектами», могут быть отправной точкой.

2
ответ дан 30 November 2019 в 06:35
поделиться

Спросите их, не хотят ли они, чтобы их заставляли выключать двигатель после езды на велосипеде, даже если двигателя нет.

Или они хотели бы вынуждены нажимать кнопку «выключить» на своем стуле, столе, чашке кофе и других предметах перед тем, как покинуть рабочее место, даже если нет ничего, что нужно было выключить.

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

Между прочим, ИМХО, отмена регистрации событий путем реализации IDisposable - подходящий способ очистки событий. Есть что "выключить".

2
ответ дан 30 November 2019 в 06:35
поделиться

IDisposable предназначен только для использования для освобождения неуправляемых ресурсов (SafeHandles и т.п.), а метод Dispose распространяется по иерархии классов. Он не предназначен для того, чтобы пытаться обойти плохие методы неуправляемого программирования.

1
ответ дан 30 November 2019 в 06:35
поделиться

В общем, если вы регистрируете обработчик с событием, то «отмена регистрации» - это просто своего рода базовая очистка, которую каждый объект должен выполнять после уничтожения. Если у вас нет деструкторов в языке, вам нужно определить метод, который будет вызывать, чтобы сообщить объекту, что он уходит. Этот метод должен очистить обработчики событий.

Разве не для этого предназначен IDisposable? Зачем вам другое решение, если оно уже есть? И почему эти болваны не реализовали свои объекты правильно? ;)

0
ответ дан 30 November 2019 в 06:35
поделиться

Создать обязанность по разрешению еще одного OutOfMemoryException. Когда кто-то разрешает чужие ошибки, это накладывает ответственность на собственный код. На ранней стадии нашего проекта нам рекомендовали «флаг дурака» - виновник фатальной ошибки получает этот флаг на день.

1
ответ дан 30 November 2019 в 06:35
поделиться

Предложите решение, которое намного превосходит их решение; -)

Например, простой альтернативой может быть использование WeakReference в долгоживущих объектах для хранения ссылок на обработчики событий. Это потребует, чтобы обработчики событий ссылались где-то еще, пока они необходимы, но как только они выходят за пределы области видимости, они собираются мусором, и слабые ссылки могут быть удалены из долгоживущих объектов.

1
ответ дан 30 November 2019 в 06:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: