Как справиться с классом, чем инкапсулирует один выпускной экземпляр?

StackOverflow https://stackoverflow.com/questions/4565661

Вопрос

interface IMyInterace
{
void Open();
object Read();
void Close();
}

class MyImplementation : IMyInterface
{
public void Open() { /* instantiates disposible class */ }
//...
public void Close() { /* calls .Dispose(); */ }

}

Есть ли хороший способ справиться с этим типом ситуации, чтобы гарантировать, что выпускные экземпляры внутри класса вызываются? (Не существует сигнала для вызывающих абонентов, что они должны назвать «закрытым», за исключением документации.) Реализации ImyInterface не обязательно инкапсулируют идентифицируемые экземпляры и неоднократно открываются и неоднократно открываются в течение всего срока службы приложения.

Я думаю о том, чтобы сделать это:

  • Реализуйте Idisposible в Myimplementation.
  • Установите Dispose () для вызова close ().
  • Добавьте звонок, чтобы закрыть () или расположить () к началу открытого, чтобы убедиться, что предыдущий вызов был закрыт.

Пользователи ImyInterface не знают, какую реализацию они используют, поэтому я не уверен, сколько ценностей делает Myimplementation Orishable, и, опять же, не все реализации будут инкапсулировать Idisposibles.

Это было полезно?

Решение

В дополнение к ответам уже здесь:

Если этот класс (часто/иногда) используется только через интерфейс, я бы посоветовал наследовать Imyinterace от iDisposable.

Это позволит вашим пользователям постоянно использовать эти объекты. Недостаток, конечно, вам, возможно, потребуется добавить (манекен) методы к классам, которые на самом деле не нуждаются в этом. Но преимущество заключается в последовательности и гибкости: что, если класс изменится в будущем, чтобы ему понадобилось утилизация ()?

Минимальный подход:

interface IMyInterace : IDisposable { }

sealed class MyImplementation : IMyInterface 
{   
   public void Open() { /* instantiates disposible class */ }

   public void Close() { /* calls _myField.Dispose(); */ }

   public void Dispose() { Close(); }  // only use this short form in a sealed class

}

Другие советы

Стандартный способ справиться с этим - просто иметь MyImplementation осуществлять IDisposable.

Как упоминал Джон, ваша первая пулевая точка - прямо.

Иногда а Close() Метод функционально синонимичен с Dispose(), и существует для поддержания семантической согласованности с абстракцией. То есть дополнить Open() метод В других случаях, Close() позволит вам вновь открыть, но Dispose() не должна. Поэтому ваша вторая точка пули также в порядке.

Пуля -точка 3 не обязательно применима, потому что утилизированный объект не следует использовать повторно. Если вам нужно позвонить Open() Опять же, вам нужно использовать новый экземпляр. На самом деле, Open() Метод должен бросить ObjectDisposedException однажды Dispose() были вызваны (проверяя частную disposed логический флаг). Если вы хотите, чтобы объект поддерживал повторное открытие после закрытия, вы можете рассмотреть возможность использования Debug.Assert() и/или бросить исключение, если Open() вызывается без Close(). Анкет Это поможет предотвратить неаккуратное управление этими случаями.

Обязательно следуйте полной одноразовой шаблоне, которая более вовлечена, чем просто реализация интерфейса:

bool disposed;

public void Dispose() // don't make virtual!
{
    Dispose(true);
    GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
    if(!disposed)
    {
        if(disposing) 
        {
            // dispose of managed resources here, for example:
            // if(resource != null) { resource.Dispose(); } 
        }
    }

    // dispose of unmanaged resources here 

    disposed = true;
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top