2013-10-24 3 views
0

Я вижу много кода, как это:Что такое ожидание IDisposable?

public class MyWcfService : IMySerciceContract, IDisposable 
{ 
    private DatabaseOperations _dataAccess; 

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

    protected virtual void Dispose(bool disposing) 
    { 
     _dataAccess.Dispose(); 
    } 
} 

Где класс MyWcfService будет размещен в IIS или WAS, где никто не будет явно вызывать Dispose на нем. Моя мысль состоит в том, что бессмысленно, чтобы этот класс реализовал IDisposable, и вам было бы лучше отключить использование _dataAccess в инструкции using. Насколько я понимаю, ожидание класса, реализующего IDisposable, заключается в том, что пользователь этого класса будет инстанцировать его в объявлении использования блока. Является ли приведенный выше пример плохой практикой, учитывая, что пользователь не будет явно вызывать Dispose? Если мы полагаемся на GC для очистки, как в приведенном выше примере, делает ли GC даже вызов Dispose или просто финализатором?

+0

Поскольку у вас есть член, который реализует IDisposable, вам следует в идеале реализовать его ... потому что ваш класс стал владельцем. См. Http: // stackoverflow.com/questions/9472304/is-there-any-benef-to-implementation-idisposable-on-classes-which-do-not-have-re ... и http://stackoverflow.com/questions/10956140/does -a-class-need-to-implement-idisposable-when-all-members-are-explicitly-dispo ..... и запускать FXCop для обнаружения любых нарушений IDisposable. Очевидно, что все, что использует ваш тип, должно вызывать Dispose (явно или неявно через использование). –

+0

GC не знает ничего о Dispose или IDisposable. Он просто вызывает финализатор. – Baldrick

+0

Но в случае такого класса обслуживания, где мы даже не ожидаем, что что-то вызовет Dispose, в чем смысл? Зачем мне реализовывать IDisposable, если я знаю, что никто не назовет Dispose? Разве я не буду лучше очищать _dataAccess самостоятельно в этом классе обслуживания? – Didaxis

ответ

1

«DatabaseOperations _dataAccess» является членом класса и является «принадлежащим» вашему классу. Это IDisposable, поэтому ваш класс тоже должен быть. И вы должны всегда применять полный шаблон диполяции для обеспечения согласованности.

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

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

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

1

..., где никто не будет явно называть Dispose на нем. Моя мысль в том, что это бессмысленно иметь этот класс реализации IDisposable ...

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

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

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

... Если мы полагаемся на GC для очистки, как в приведенном выше примере, делает ли GC даже вызов Dispose или только финализатором?

GC не вызывается автоматически Dispose, поэтому для его активации потребуется финализатор.

public partial class MyWcfService: IMySerciceContract, IDisposable { 
    private DatabaseOperations _dataAccess; 

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

    protected virtual void Dispose(bool disposing) { 
     if(!this.disposed) { 
      if(disposing) { 
       _dataAccess.Dispose(); 
      } 

      this.disposed=true; 
     } 
    } 

    // so it make sense now .. 
    ~MyWcfService() { 
     this.Dispose(false); 
    } 

    bool disposed; 
} 

Если Dispose не вызывается потребителем, финализатор вызывает его при необходимости. Посмотрите, как реализовать [IDisposable interface].

+0

Неплохой ответ, хотя Я полностью понимаю, что мы не реализуем IDisposable ради использования операторов lol. Я достаточно хорошо понимаю концепцию RAII, мой вопрос был больше о том, когда нужно очищать одноразовые предметы и где эта ответственность должна приниматься. – Didaxis

+0

@Didaxis: для ** когда **, я думаю, КАК МОЖНО СКОРЕЕ, когда вы уверены в том, что одноразовые объекты не должны использоваться впоследствии. Если '_dataAccess' приобретается экземплярами' MyWcfService', тогда 'MyDcfService' должен отвечать за' _dataAccess'. Для **, где **, является кодом, который я предложил, который совпадает с руководством MSDN. –

+0

спасибо за этот ответ. Я отметил ответ Бальдрика как правильный, потому что я думаю, что он более непосредственно затрагивает мой вопрос. Тем не менее, вы были полезны! Кроме того, что случилось с комментарием о моей грамматике? (просто любопытно) – Didaxis

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