Использование определенных шаблонов для реализации интерфейсов

В последнее время меня очень интересовали шаблоны проектирования, и, в частности, следование правильным шаблонам проектирования в моих классах, которые реализуют один или несколько интерфейсов.

Давайте рассмотрим пример. Когда класс реализует IDisposable , вы должны следовать определенному шаблону, чтобы убедиться, что ваши ресурсы должным образом очищены, путем создания частного метода Dispose (bool dispose), который различает, вызывается ли он финализатором или если он вызывается из общедоступного метода Dispose. Кроме того, в этом случае должен быть реализован финализатор, и вам также может потребоваться частная переменная типа bool с именем isDisposed, которая устанавливается методом Dispose, чтобы любой метод, вызываемый после того, как объект был Disposed, вызывал исключение, давая понять, что этот объект уже удален, вместо того, чтобы сбой кода внутри метода из-за удаления некоторых необходимых ресурсов, и поэтому больше не доступны.

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

Некоторые примеры интерфейсов, которые я хотел бы лучше всего реализовать, - это ISerializable, IComparable, IComparable <>, ICloneable, IEnumerable <> и так далее. Здесь интересны все интерфейсы из Framework, поэтому его не следует ограничивать перечисленными выше.

Мне нужны разные интерфейсы, предпочтительный способ и, надеюсь, также ссылка на ресурс в Интернете, который объясняет, как и почему следует следовать определенному шаблону.

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

. Было бы здорово, если бы для одного интерфейса было несколько шаблонов, чтобы мы могли обсудить, какой из них предпочтительнее. Это также может привести к тому, что некоторые из вас, возможно, перейдут на новый шаблон или внесут изменения в существующие шаблоны, чтобы еще больше улучшить ваш код, и это было бы здорово!

Изменить

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

Редактировать 2

Мне, вероятно, следует начать это я сам, так как я поставил вопрос здесь. Поэтому я опишу один шаблон, который мне хорошо известен, и это шаблон IDisposable.

Этот шаблон следует использовать только в том случае, если ваш класс содержит один или несколько неуправляемых ресурсов внутри вашего класса, и вы должны убедиться, что они удаляются. . в этом случае в дополнение к методу Dispose нам понадобится финализатор на случай, если пользователь вашего класса забудет его удалить.

Итак, обо всем по порядку. Ваш класс должен реализовывать интерфейс IDisposable, и вам нужно будет определить общедоступный метод Dispose как управляемый интерфейсом. Этот метод должен выглядеть следующим образом:

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

Это вызовет защищенный метод Dispose (bool), который позаботится о фактической очистке.

Кроме того, включите vaiable в свой класс, чтобы указать, удален ли класс или нет:

private bool alreadyDisposed = false;

GC.SuppressFinalize сообщает сборщику мусора, что этот элемент не нужно финализировать, даже если у него есть финализатор.

Затем вам понадобится защищенный метод Dispose. Сделайте его защищенным, а не закрытым, на случай, если какой-либо производный класс должен его переопределить:

protected virtual void Dispose(bool isDisposing)
{
  if (alreadyDisposed)
  {
    return;
  }
  if (isDisposing)
  {
    // free all managed resources here
  }
  // free all unmanaged resources here.
  alreadyDisposed = true;
}

Финализатор также должен вызвать Dispose (bool), если пользователь забывает очистить:

~SomeClass(){
  Dispose(false);
}

Если некоторый метод требует для работы удаленного ресурса, make функция такая:

public void SomeMethod()
{
  if (alreadyDisposed)
    throw new ObjectDisposedException("SomeClass",
                                      "Called SomeMethod on Disposed object");
  // Method body goes here
}

Вот и все. Это гарантирует, что ресурсы будут очищены. Предпочтительно для пользователя вашего класса, вызывающего Dispose, но путем добавления Finalizer в качестве резервного метода.

6
задан Øyvind Bråthen 14 September 2010 в 13:45
поделиться