2015-11-10 2 views
2

Допустим, у меня есть объект C, который содержит ссылки на экземпляры самого себя, а также реализует IDisposable. Как удалять ссылки на другие экземпляры C? Должен ли я рекурсивно называть их методы dispose или я должен просто установить их равными нулю? Другими словами, какая из следующих моделей предпочтительна?C# - Утилизация рекурсивных объектов

Модель 1: Рекурсивный Утилизация

public class C : IDisposable 
{ 
    public List<C> subItems = new List<C>(); 

    public void Dispose() 
    { 
     foreach (C subItem in subItems) 
      subItem.Dispose(); 
     // Dispose other stuff 
    } 
} 

Модель 2: Располагая приравнивая к null

public class C : IDisposable 
{ 
    public List<C> subItems = new List<C>(); 

    public void Dispose() 
    { 
     subItems = null; 

     // Dispose other stuff 
    } 
} 
+0

Умм, модель 2 не располагая подпунктами. –

+0

Почему ваш класс IDisposable? –

+0

@HenkHolterman У меня не было причин в виду, я просто интересовался своей образовательной выгодой. Это всего лишь абстрактная модель. – user3002473

ответ

8

Должен ли я рекурсивно называть их Dispose методы

Да.

Но только тогда, когда C действительно должен быть IDisposable, что не очевидно из вашего кода. Тот факт, что он ссылается на экземпляры одного и того же класса, не имеет значения, вызовите Dispose() для всех принадлежащих IDisposable объектов.

Если это попытка «помочь» сборщику мусора, прекратите его и просто ничего не сделайте.

+1

Однако будьте осторожны с циклами в графе объектов! –

+0

Скотт, да, стандартный шаблон вызывает булевое поле 'isDisposed'. Большинство проблемных областей будут избегать/запрещать циклы, а затем опубликованный код в порядке (-ish). –

+0

Следует отметить, что GC ** никогда ** не вызывает '.Dispose()', если нет финализатора, который явно делает это. – Enigmativity

-1

Должен ли я рекурсивно называть их Dispose методы

Нет, если вам не нужно это. (GC очистил его)

Да. если объект использует неуправляемые ресурсы. Не избавление от неуправляемых ресурсов приведет к утечке памяти.

+0

_Не избавление от неуправляемых ресурсов приводит к утечке ресурсов. Это не имеет никакого отношения к использованию памяти. –

+0

_It не имеет ничего общего с использованием памяти. Я имею в виду в обычном режиме. –

+0

_В общем или нет, это часто повторяющийся миф, который просто не соответствует действительности. Dispose() предназначен для очистки ресурсов. Это не альтернатива GC. –

-1

Это не только правильный ответ.

Главный вопрос, который вы должны СПРОСИТЬ - это ПОМОЩЬ LIST реального и единственного ВЛАДЕЛЬЦА элементов в нем?

Если да - единственный действующий поведение - звоните Dispose явно (как в первом псевдокоде)

Если элементы или могут быть общими и могут быть использованы в других контекстах, а не один контейнер (например, в это с StreamWriter и Stream - StreamWriter может быть «владельцем» Stream и закрывать его, но вы можете использовать параметр keepLive, чтобы Stream был открыт). В общем случае единственный выход из таких ситуаций - из-за того, что если вы распоряжаетесь - вы можете нарушить другие задачи, если не распоряжаться и просто очистить список - вы можете сохранить часть ресурсов без каких-либо шансов на очистку.

Где Ниндзя путь для общего, как это цветовым в shared_ptr в C++ или обычные ссылки в .NET - трассировки счетчика использования -

class C:IDisposable{ 
    int usageCount = 0; 
    public void AddUsage(){usageCount++;}; 
    public void Dispose(){ 
     if(usageCount>0){ 
      usageCount--; 
      return; 
     } 
     //ELSE DO REAL DISPOSE LOGIC 
    } 
} 

НО жаль, что это не ваш случай)

Смежные вопросы