2015-12-16 4 views
3

У меня есть класс, который реализует С # SerialPort, который используется для выглядеть следующим образом:Реализация IDisposable правильно на родительских классов в C#

public class AsyncSerial : IDisposable 
{ 
    SerialPort newPort; //Parameters declared in my constructor 
    //Constructor and other methods 

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

    protected virtual void Dispose(bool disposing) 
    { 
     if(disposing) 
     { 
      this.Close(); 
      this.Dispose(); 
     } 
    } 
} 

Это не бросает никаких предупреждений анализа кода (я получил код от MSDN, как пример того, как это сделать правильно).

Поскольку я только собирался объявить один SerialPort, я решил, что сделаю мой класс дочерним по отношению к SerialPort, но теперь я получаю предупреждения, которые я не могу исправить.

public class AsyncSerial : SerialPort 
{ 
    //Constructor and other methods 

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

    protected new virtual void Dispose(bool disposing) 
    { 
     if(disposing) 
     { 
      this.Close(); 
      this.Dispose(); 
     } 
    } 
} 

предупреждения Кодовые сказал Dispose методы должны быть new как они скрывают члены, которые я сделал, но я также получаю:

«Предупреждение CA1063 Убедитесь, что 'AsyncSerial.Dispose() объявлен в общественных и запечатаны»

Создание запечатанной означает, что он должен быть отмечен override (или я получаю ошибки компилятора), что делает его переопределения означает, что он может быть новым, так что я в конечном итоге с:

CS0506 Ошибка 'AsyncSerial.Dispose()': не может переопределить унаследованное элемент 'Component.Dispose()', поскольку он не отмечен виртуальный, аннотация, или переопределить

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

public class AsyncSerial : SerialPort, IDisposable 
{ 
    //code 
} 

дает мне предупреждение анализа кода, потому что SerialPort уже реализует IDisposable.

Должен ли я просто подавлять предупреждение о том, что «AsyncSerial.Dispose()» объявляется публичным и запечатанным, или есть правильный способ сделать это, что не дает предупреждения о анализе кода.

+1

Встраивание SerialPort в порядке, но вам нужно всего лишь утилизировать его в методе Dispose(), ничего больше и нет необходимости в одноразовом шаблоне. Не стесняйтесь использовать * запечатанный *. Наследование тоже прекрасное, но тогда вам нужно * только * переопределить Dispose (bool) и не наследовать IDisposable. Так как у вас нет ничего лишнего, что не нужно. –

ответ

8

Ваш подкласс должен переопределить Dispose(bool disposing), если что-нибудь - в этом весь смысл иметь этот метод вообще.

Однако, я подозреваю, что базовый класс будет принимать правильные звонки в любом случае, так что вам не нужно ничего делать, если у вас есть дополнительные ресурсы для освобождения которых не выпущена в Close(). Если это так, то сделать это в Dispose(bool disposing):

protected override void Dispose(bool disposing) 
{ 
    // Allow the base class to release resources 
    base.Dispose(disposing); 
    // Release any extra resources here 
} 

Обратите внимание, что текущая реализация приведет к StackOverflowException как ваши два Dispose перегрузок называют друг друг.

+0

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

0

Вам не нужно объявлять метод public void Dispose() в дочернем классе, поскольку он уже был унаследован от базового (компилятор не позволит вам в любом случае, если вы не скроете базовую реализацию с помощью ключевого слова new).

Вы также не должны переопределять базовый класс protected virtual void Dispose(bool), если вы не собираетесь использовать что-либо конкретное для этого дочернего класса.

Если вы должны были иметь IDisposable ссылки в своем классе ребенка, то вы должны переопределить метод вашего базового класса:

public class AsyncSerial : SerialPort, IDisposable 
{ 
    // SomeClass implements IDisposable 
    private SomeClass _disposableInstance; 

    // ... 

    protected override void Dispose(bool disposing) 
    { 
     if(disposing) 
     { 
      if(_disposableInstance != null) 
       _disposableInstance.Dispose(); 
     } 

     // Call the base Dispose, to release resources on the base class. 
     base.Dipose(disposing); 
    } 
} 
1

Dispose шаблон был разработан, чтобы производные типов добавить логику удаления в последовательном независимо от того, имеет ли родительский тип общедоступный метод Dispose или реализует IDisposable.Dispose явно. Типы, которые производятся от типа, следующего за шаблоном, должны просто переопределять Dispose(bool) независимо от того, как реализуется родительский класс, использует открытый метод или явную реализацию для IDisposable.Dispose().

Хотя дизайн шаблона Dispose был основан на ошибочном предположении, что публично выставленные объекты наследуемых типов часто должны включать финализаторы напрямую (а не инкапсулировать неуправляемые ресурсы в частные экземпляры частных типов, целью которых является очистка этих ресурсов), логика очистки, созданная компилятором в C++/CLI (и, возможно, другие языки), опирается на шаблон и поэтому неплохо использовать его с наследуемыми классами, которые могут использоваться другими людьми.

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

  • Нет связанных вопросов^_^