Каковы альтернативные варианты использования IDisposable? - PullRequest
1 голос
/ 24 мая 2011

Документация msdn интерфейса System.IDisposable гласит, что

Использование основного этого интерфейса для освобождения неуправляемых ресурсов.

Мне интересно, каковы альтернативные варианты использования.

Например, нам также был необходим интерфейс IDisposable для других выделенных ресурсов, таких как подписка на события и т. Д.

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

Когда мы выбрали интерфейс IDisposable для такого поведения, мы рассматривали его как альтернативное (недокументированное) использование интерфейса.

альтернативное использование IDisposable вы нашли?Они законны?Документация MSDN неверна?

Ответы [ 6 ]

2 голосов
/ 24 мая 2011

Я думаю, что вы читаете документацию неправильно.Сказать, что любое использование IDisposable, не связанное с неуправляемыми ресурсами, недокументировано, все равно, что сказать, что любое использование System.Int32, которое не считает, недокументировано.Это интерфейс и не имеет реализации, там нет функциональности, чтобы даже начать различать то, что задокументировано, а что нет.

Цель IDisposable состоит в том, чтобы просто предоставить разработчику механизм для детерминированного управления временем жизни их объектов.Так уж сложилось, что это в основном требование для работы с неуправляемыми ресурсами.

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

Пример 1 - блоки синхронизации

StackOverflow использует мини-профилировщик , который используетusing блоков для определения вложенных областей исполнения:

using (profiler.Step("Doing complex stuff"))
{
    using (profiler.Step("Step A"))
    { // something more interesting here
        Thread.Sleep(100);
    }
    using (profiler.Step("Step B"))
    { // and here
        Thread.Sleep(250);
    }
}

Альтернатива неиспользованию using довольно ужасна, и я даже не хочу ее здесь высмеивать.

Пример 2. Одноразовое действие

В кругах .NET Domain Driven Design были различные варианты создания одноразовых шаблонов действий.У Айенде есть один , так же, как и у Уди Дахана в его реализации Domain Events , у Джимми Богарда немного другое восприятие этого , все еще в контексте событий домена.Суть шаблона в том, что вы хотите выполнить определенные действия в некотором контексте, а затем вернуть контекст обратно к тому, что был раньше после того, как вы это сделали.

Айенде приводит простой пример:

class UsuallyReadOnly { 
  //.. implementation
  public IDisposable AllowModification
  {
    get 
    {
        _allowModification = true;
        return new DisposableAction(()=>{ _allowModification = false; } );
     }
  }
}

И UsuallyReadOnly использование:

UsuallyReadOnly foo = new UsuallyReadOnly();
using(foo.AllowModification)
{
  foo.Name = "Bar";
}
2 голосов
/ 24 мая 2011

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

1 голос
/ 24 мая 2011

Вместо «ресурсы» заменить «обязанности». Когда говорят, что объект содержит неуправляемый ресурс, это на самом деле означает, что есть какое-то задание, которое нужно выполнить когда-нибудь, и объект - это единственная вещь, обладающая информацией и импульсом, необходимыми для этого. Цель «Распоряжения» состоит не в том, чтобы избавиться от какой-либо материальной сущности, а в том, чтобы позволить объекту «навести порядок». Кто-то наводит порядок в своих делах до того, как его смерть ничего не делает для себя, а скорее он гарантирует, что то, что он должен сделать с людьми и вещами вне себя, будет сделано. Аналогично с IDisposable.Dispose.

0 голосов
/ 06 мая 2013

Посмотрите на следующий вопрос Нужна альтернатива моему IDisposable Hack

Там я привожу хороший пример того, для чего я использовал IDisposable.:)

Конечно, это не идеальное решение, но оно мне очень помогло.

0 голосов
/ 24 мая 2011

Одним из наиболее популярных применений интерфейса IDisposable являются области транзакций. Вы можете использовать его, чтобы обернуть некоторую логику SQL в транзакцию, и явно вызвать Complete(), чтобы завершить транзакцию:

using (var scope = new TransactionScope())
{
    using (var connection = new SqlConnection(connectString))
    {
        // perform sql logic
        ...

        scope.Complete(); 
    }
}

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

public class TempFileProvider : IDisposable
{
    public Filename { get; private set; }

    public TempFileProvider()
    {
        Filename = Path.GetTempFileName();
    }

    public void Dispose()
    {   
        File.Delete(Filename);
    }
}

Так что вы можете использовать его как:

using (var tempFileProvider = new TempFileProvider())
{
    DoSomethingWithFile(tempFileProvider.Filename);
} // deletes temp file
0 голосов
/ 24 мая 2011

Помните, что есть также шаблон с использованием , который немного похож на RAII .

using ( DisposableObject obj = new DisposableObject( ) )
{

    .....
}

Итак, Dispose вызывается при выходе из блока using.

...