Завершение / Утилизация шаблона в C # - PullRequest
360 голосов
/ 22 мая 2009

C # 2008

Я уже некоторое время работаю над этим, и я все еще не понимаю некоторые вопросы. Мои вопросы ниже

  1. Я знаю, что вам нужен финализатор, только если вы избавляетесь от неуправляемых ресурсов. Однако если вы используете управляемые ресурсы, которые выполняют вызовы к неуправляемым ресурсам, вам все равно потребуется реализовать финализатор?

  2. Однако, если вы разрабатываете класс, который не использует какие-либо неуправляемые ресурсы, прямо или косвенно, можете ли вы реализовать IDisposable, чтобы клиенты вашего класса могли использовать «оператор using»?

    Было бы приемлемо реализовать IDisposable только для того, чтобы клиенты вашего класса могли использовать оператор using?

    using(myClass objClass = new myClass())
    {
        // Do stuff here
    }
    
  3. Я разработал этот простой код ниже, чтобы продемонстрировать шаблон Finalize / dispose:

    public class NoGateway : IDisposable
    {
        private WebClient wc = null;
    
        public NoGateway()
        {
            wc = new WebClient();
            wc.DownloadStringCompleted += wc_DownloadStringCompleted;
        }
    
    
        // Start the Async call to find if NoGateway is true or false
        public void NoGatewayStatus()
        {
            // Start the Async's download
                // Do other work here
            wc.DownloadStringAsync(new Uri(www.xxxx.xxx));
        }
    
        private void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            // Do work here
        }
    
        // Dispose of the NoGateway object
        public void Dispose()
        {
            wc.DownloadStringCompleted -= wc_DownloadStringCompleted;
            wc.Dispose();
            GC.SuppressFinalize(this);
        }
    }
    

Вопрос по исходному коду:

  1. Здесь я не добавил финализатор, и обычно финализатор вызывается GC, а финализатор вызывает Dispose. Поскольку у меня нет финализатора, когда я вызываю метод Dispose? Это клиент класса должен вызывать его?

    Так что мой класс в примере называется NoGateway, и клиент может использовать и распоряжаться этим классом так:

    using(NoGateway objNoGateway = new NoGateway())
    {
        // Do stuff here   
    }
    

    Будет ли метод Dispose автоматически вызываться, когда выполнение достигает конца блока using, или клиент должен вручную вызывать метод dispose? т.е. * * тысяча тридцать три

    NoGateway objNoGateway = new NoGateway();
    // Do stuff with object
    objNoGateway.Dispose(); // finished with it
    
  2. Я использую класс webclient в своем классе NoGateway. Поскольку веб-клиент реализует интерфейс IDisposable, означает ли это, что веб-клиент косвенно использует неуправляемые ресурсы? Есть ли жесткое и быстрое правило, которому нужно следовать по этому поводу? Как мне узнать, что класс использует неуправляемые ресурсы?

Ответы [ 13 ]

2 голосов
/ 22 мая 2009

1) WebClient является управляемым типом, поэтому вам не нужен финализатор. Финализатор необходим в том случае, если ваши пользователи не Dispose () вашего класса NoGateway и после этого необходимо очистить собственный тип (который не собирается GC). В этом случае, если пользователь не вызывает Dispose (), содержащийся в нем WebClient будет удален GC сразу после того, как это сделает NoGateway.

2) Косвенно да, но вам не нужно об этом беспокоиться. Ваш код верен, и вы не можете помешать пользователям легко забыть Dispose ().

2 голосов
/ 22 мая 2009
using(NoGateway objNoGateway = new NoGateway())

эквивалентно

try
{
    NoGateway = new NoGateway();
}

finally
{
    NoGateway.Dispose();
}

Финализатор вызывается при GC, уничтожающем ваш объект. Это может быть в совершенно другое время, чем когда вы покидаете свой метод. Dispose of IDisposable вызывается сразу после того, как вы покинете блок using. Следовательно, шаблон обычно используется для освобождения ресурсов сразу же после того, как они вам больше не нужны.

0 голосов
/ 22 мая 2009

Насколько я знаю, настоятельно рекомендуется НЕ использовать Финализатор / Деструктор:

public ~MyClass() {
  //dont use this
}

В основном это происходит из-за незнания, когда или ЕСЛИ это будет вызвано. Метод утилизации намного лучше, особенно если вы используете или утилизируете напрямую.

использование это хорошо. используйте это:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...