Объект с подсчетом ссылок на него

193
18 января 2019, 05:20

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

В C++ это бы сделать не составило труда, задать приватный метод, и подружить данный класс с теми кто может увеличивать/уменьшать количество ссылок. Но как хотя бы примерно такое реализовать на C# ума не приложу.

Необходимо все это дело для реализации фабрики.

Answer 1

Как вариант можно добавить в класс счетчик ссылок

public class Foo : IDisposable
{
    private int _refCounter = 0;
    public void IncRef() { _refCounter++; }
    public void DecRef() 
    {
        _refCounter--;
        if(refCounter <= 0) Dispose();
    }
    public void Dispose()
    {
        //Dispose impl here
    }
}

А в классе, которому будет присваиваться этот объект в свойстве необходимо реализовать увеличение количества ссылок при set и уменьшение при перезаписи

public class Bar
{
    ~Bar()
    {
       FooInstance = null;
    }
    private Foo _FooInstance;
    public Foo FooInstance
    { 
       get => return  _FooInstance;
       set 
       {
           _FooInstance?.DecRef();
           value?.IncRef();
           _FooInstance = value;
       }
    }
}

Но тут проблема в том, что ссылки будут считаться только когда объект будет присваиваться к полям, а в случае переменных это работать не будет. Однако этой задачей занимается сборщик мусора, а если необходимо освобождать ресурс, как только он перестал использоваться, то, наверное этот "костыль" должен подойти, но более правильным подходом было бы найти места в коде, где ресурс точно должен освобождаться и вызывать метод Dispose. Но, если это невозможно, то самым правильным способом было бы использование финализатора. Как правильно его объявить для IDisposable можно посмотреть тут.

Если используется unmanaged ресурс, то есть смысл использовать для этого SafeHandle, в нем, если я не ошибаюсь, подсчет количества ссылок реализован на уровне компилятора.

READ ALSO
Программно открыть cmd.exe от имени администратора и перенаправить потоки ввода и вывода

Программно открыть cmd.exe от имени администратора и перенаправить потоки ввода и вывода

Пишу небольшую утилиту, которая имеет необходимость раз в несколько секунд выполнять какую-либо команду командной строке Windows от имени администратораСоздавать...

107
Порядок действий метода JsonConvert.DeserializeObject

Порядок действий метода JsonConvert.DeserializeObject

У меня есть классМне нужно делать таких экземпляров много

138
Unixtimestamp в Datetime

Unixtimestamp в Datetime

Есть время 1538122139000Хочу его сконвертировать в DateTime

136
Как достать номер версии и билда приложения с Jenkins?

Как достать номер версии и билда приложения с Jenkins?

У меня есть приложение на c#, которое билдится на JenkinsНомера билдов идут по порядку от 1 до 23 на данный момент

179