Статические одноразовые предметы

  • Как мне управлять классами static с одноразовыми элементами? Существуют ли какие-либо эмпирические правила?

  • В принципе, должен ли я рефакторинг и сделать следующий DisposableDataManager класс non- static, или это прекрасно, чтобы оставить все в GC?

.

public static class DisposableDataManager
{
    // ImageList is an 'IDisposable'.
    public static ImageList FirstImageList { get; private set; }
    public static ImageList SecondImageList { get; private set; }

    static DisposableDataManager()
    {
        FirstImageList = CreateFirstImageList();
        SecondImageList = CreateSecondImageList();        
    }

    // ...
}

Ответ 1

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

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

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

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

Ответ 2

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

Ответ 3

Вы можете подключить событие AppDomain.DomainUnload и вызывать dispose на все, что вы хотите, чтобы убедиться, что он очищен до вашего выхода.

Ответ 4

Что я вижу из этого кода, вы не сможете распоряжаться ImageList, так как DisposableDataManager является статическим классом, который будет доступен до закрытия приложения.

Ответ 5

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

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

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

Ответ 6

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

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

Или вы можете изменить ImageList, чтобы не быть одноразовым вообще. Это был бы вариант, только если вы можете распоряжаться всеми ресурсами, которые он держит сам.

Ответ 7

Я не думаю, что вам нужно сделать любой менеджер одноразовых объектов. GC уже управляет памятью для вас. Как вы, наверное, уже знаете, метод Dispose - это тот, который исходит из интерфейса IDisposable, включенного в .Net framework. Но это метод, подобный любому другому *. Сборщик мусора не ждет, чтобы Dispose вызывается для освобождения памяти объекта. Он контролирует, когда объект всегда доступен где-то или нет. Это поможет ему определить, какой объект жив и кто мертв.

Прежде чем продолжить читать немного о генерации GC. http://msdn.microsoft.com/en-us/library/ms973837.aspx

Я не уверен, но когда new() является вызовом, а GC достигает емкости фактического используемого поколения, он очищает "мертвые" объекты следующего поколения. Наверное, в другое время я этого не делаю. GC - такая мистическая и таинственная реализация, потому что, вероятно, она работает на С++. Но вам не нужно заботиться об этом.

В некоторых случаях (моноразработка) я слышал, что вы должны больше заботиться об этом. Но не если вы код в среде Microsoft.

* Я сказал:

как и любой другой

но блок использования дает вам свободу называть метод Dispose объектов IDisposable и вызывать метод для вас. Существующее существо метода Dispose - освободить ресурсы, которые должны быть выпущены до прекращения использования объекта.

Пример:

    public class Test : IDisposable
    {
        public void Dispose()
        {
            // release other necessary ressources if needed

            Console.WriteLine("Disposed");
        }
    }


    {
        using (IDisposable disposable = new Test())
        {

        }
    }

то же самое, что:

{
    IDisposable disposable = new Test()
    disposable.Dispose();
}

Итак, вы можете быть уверены в GC. Если вы хотите быть уверены, что GC освободит вас от памяти объекта, просто сделайте все ссылки на него равными нулю. И GC рассмотрит ваш объект как "мертвый": P