Должен ли класс stati c утилизировать свои переменные IDisposable в деструкторе stati c? - PullRequest
2 голосов
/ 18 марта 2020

Если у класса stati c есть переменные IDisposable stati c, должен ли этот класс иметь "деструктор stati c" для их удаления? Например:

public static StaticClass
{
    static SomeDisposableType
        someDisposable = new SomeDisposableType();

    static readonly StaticDestructor
        staticDestructor = new StaticDestructor();

    private sealed class StaticDestructor
    {
        ~StaticDestructor()
        {
            someDisposable.Dispose();
        }
    }
}

Ответы [ 2 ]

2 голосов
/ 18 марта 2020

Нет, не должно.

У среды выполнения нет возможности узнать , когда ваш класс c будет использоваться в течение последнего времени. Он не может знать, что может вызвать очистку на ранней стадии.

Следовательно, единственное "разумное" время для выполнения очистки - это когда весь процесс собирается завершиться. Но сейчас не время для уборки. Для аналогичного, неуправляемого, возьмите это, прочитайте Рэймонда Чена * Когда DLL_PROCESS_DETACH сообщает вам, что процесс завершается, вам лучше всего просто вернуться, ничего не делая :

здание сносится. Не беспокойтесь о том, чтобы подметать пол и опустошать банки sh и стирать доски.

Теперь некоторые могут выдвинуть аргумент, что некоторые из ваших одноразовых принадлежностей могут представлять external ресурсы, которые не будут очищены / освобождены, когда ОС разрушает ваш процесс. Хотя это и правда, эти внешние ресурсы должны справляться, например, с прекращением процесса пользователем или (если не на одном и том же компьютере) сбоем электропитания, отнимающим всю машину. Вы не можете запустить какой-либо код очистки при отключении электричества. Таким образом, они уже должны быть закодированы для того, чтобы ваш процесс не смог освободить ресурсы.

1 голос
/ 18 марта 2020

Здесь происходят некоторые запахи кода.

  1. StaticClass тесно связан с указанными c типами, от которых он зависит, а не только с их интерфейсами.
  2. StaticClass определяет срок службы сервисов, которые он использует.

Это не позволяет StaticClass быть полностью тестируемым модулем. Например, вы не можете протестировать поведение StaticClass, не протестировав также и поведение SomeDisposableType.

Я бы почти всегда рекомендовал сделать ваш StaticClass нестатичным c и использовать инжектор конструктора для внедрения сервисов, которые зависят от него. в качестве интерфейсов, что позволяет конфигурации среды Dependency Injection определять время жизни этих объектов.

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

Если есть , это убедительная причина, чтобы StaticClass был единственным, подумайте очень серьезно о вашем разделении интересов. : StaticClass делает слишком много? Например, возможно, он выполняет некоторую работу по поиску значений, а затем сохраняет эти значения, чтобы избежать повторного выполнения этой работы позже. Или, возможно, он сохраняет состояние определенных свойств вашего приложения и действует на основе этого состояния. В этих случаях вы обычно можете разделить работу по сохранению состояния или запоминанию / кэшированию в отдельном классе, который может быть привязан к одиночке. Тогда ваш сервис, который использует это состояние или кэшированные значения, все еще может быть временным, а его одноразовые зависимости все еще могут быть утилизированы после выполнения заданного задания c.

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

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

...