Подтвердить что ты не робот

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

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

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

class Context : IDisposable
{
    // Put a new context onto the stack
    public static void PushContext() { ... }

    // Remove the topmost context from the stack
    private static void PopContext() { ... }

    // Retrieve the topmost context
    public static Context CurrentContext { get { ... } }

    // Disposing of a context pops it from the stack
    public void Dispose()
    {
        PopContext();
    }
}

Использование кода вызова может выглядеть так:

using (Context.PushContext())
{
   DoContextualStuff(Context.CurrentContext);
} // <-- the context is popped upon leaving the block

(Обратите внимание, что это всего лишь пример, а не тема этого вопроса.)

Тот факт, что Dispose() вызывается из области действия оператора using, также может быть использован для реализации всех видов вещей, которые зависят от области видимости, например. таймеры. Это также можно было бы использовать с помощью конструкции try ... finally, но в этом случае программисту пришлось бы вручную вызвать какой-либо метод (например, Context.Pop), который конструктор using мог бы сделать для thon.

Это использование IDisposable не совпадает с его назначением как указано в документации, однако искушение сохраняется.

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

4b9b3361

Ответ 1

Итак, в представлениях MVC MVC, мы видим следующую конструкцию:

using(Html.BeginForm())
{
    //some form elements
}

Оскорбление? Microsoft говорит "нет" (косвенно).

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

Ответ 2

"Это злоупотребление интерфейсом IDisposable, чтобы использовать его таким образом"? Возможно.

Использует ли using как чисто "область видимости" для более очевидного намерения и лучшей читаемости кода? Конечно.

Последний козыряет первое для меня, поэтому я говорю, что использую его.

Ответ 3

Вы, конечно, не были бы первым, кто "злоупотреблял" IDisposable таким образом. Вероятно, мое любимое использование в таймерах, так как клиент StatsD.NET демонстрирует:

using StatsdClient;
...
using (statsd.LogTiming( "site.db.fetchReport" ))
{
  // do some work
}
// At this point your latency has been sent to the server

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