Что этот IDisposable делает для меня? - PullRequest
6 голосов
/ 06 декабря 2011

Я работаю над «учебной программой» и использую инструмент рефакторинга Code Rush в процессе обучения.С последним обновлением Code Rush он рекомендует использовать IDisposable для моих программ.Я знаю, что MSDN говорит о IDisposable, и у меня есть базовое понимание того, что он делает, но, поскольку я не знаю всех последствий его реализации, я игнорирую эту рекомендацию.Сегодня я решил узнать больше об этом и согласился с рекомендацией.

Это то, что он добавил в мою программу.

class Program : IDisposable
{
    static Service _proxy;

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
            if (_proxy != null)
            {
                _proxy.Dispose();
                _proxy = null;
            }
    }

    ~Program()
    {
        Dispose(false);
    }

Так что мои вопросы таковы.Делает ли это все, что мне нужно, чтобы получить преимущество IDisposable, или мне нужно что-то делать в коде, чтобы он работал?Я поставил точки останова на этом и никогда не достигал его через отладчик, поэтому либо он не был нужен, либо я не использую его так, как было задумано.Может кто-нибудь, пожалуйста, пролить некоторый свет на то, что это делает для меня или как я должен использовать это, чтобы это что-то сделало для меня?

Ответы [ 2 ]

10 голосов
/ 06 декабря 2011

В этом случае CodeRush предлагает вам реализовать IDisposable, потому что ваш класс инкапсулирует ресурс IDisposable (он видит _proxy, хотя это не совсем хорошо, так как он статичен).Code Rush считает, что есть тип, который вы используете, который должен быть явно очищен, но вы не предоставляете способ сделать это через ваш класс.

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

Кроме того, этот класс не должен реализовать IDisposable (если нет других причин для этого), учитывая приведенный выше код, поскольку ресурс _proxy равен static.Удаление статического ресурса из экземпляра может вызвать проблемы, по крайней мере, в общем случае.(В этом случае это, очевидно, не проблематично, но это не очень хорошая практика ...) Как правило, статическая переменная имеет очень другое время жизни, чем член экземпляра, поэтому ее автоматическое удаление будет неуместным.

0 голосов
/ 06 декабря 2011

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

  1. Какой-то другой объект также будет хранить ссылку, по крайней мере, до тех пор, пока Foo нуждается в ней, и будет заботиться о вызове Dispose для него, поэтому Foo должен позволить другому объекту позаботиться о Dispose.
  2. Объект, содержащий ссылку, будет последним, кто будет использовать рассматриваемый объект IDisposable; если Foo не вызывает Dispose, больше ничего не будет. В этом сценарии Foo должен убедиться, что метод Dispose другого объекта вызывается, когда он (Foo) больше не нужен, и до того, как от него отказались. Самый идиоматичный способ справиться с этим - это для Foo реализовать IDisposable.Dispose и для его метода Dispose для вызова Dispose для объектов IDisposable, на которые он хранит последние полезные ссылки.

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

...