Я работаю над проектом.NET, который должен взаимодействовать с некоторыми определяемыми пользователем классами - отнесенный в как "задания". Все классы задания должны реализовать определенный интерфейс IJob
в порядке заказывают для библиотеки для потребления их. Иногда класс задания мог бы содержать неуправляемый ресурс, который должен быть явно расположен.
Как я должен удостовериться, что все задания правильно расположены после использования, если я не знаю заранее, нужно ли для задания явное распоряжение? Я имею несколько идей сам, но хотел бы услышать Ваши комментарии/предложения:
Сделать IJob : IDisposable
, то, чтобы вынуждать все задания реализовать a Dispose()
метод. Это позволит мне работать с заданиями в using
блоки, но поскольку для большинства заданий, как ожидают, не будет нужно явное распоряжение, это могло бы добавить ненужный беспорядок для разработчиков клиента.
Делайте всю работу, вовлекающую работы в try-finally
блоки и использование finally
гарантировать это Dispose()
назван, если задание реализует IDisposable
. Это помогает клиентам реализовать новый класс задания - не имея необходимость реализовать пустое Dispose()
метод - но это также скрывает то, что библиотека знает и заботится о доступных заданиях.
После описывания этого я склонен склоняться к решению № 1, но я все еще думаю, что было бы хорошо видеть альтернативные решения и дополнительных профессионалов/недостатки к двум, которые я уже имею в виду.
Есть прецедент: Базовый класс Stream является IDisposable nad, следовательно, все потомки Streams являются таковыми. Но MemoryStream не нуждается в утилизации.
Но не пытайтесь/не пытайтесь, блок using() { }
является более удобным словосочетанием. Итак, ваш выбор: Ты хочешь, чтобы все вакансии были одноразовыми или просто одноразовыми?
Первый вариант имеет небольшие накладные расходы, второй позволяет легче забыть об утилизации (использовании), когда это необходимо.
#2, как работает конструкция foreach
. Так же работает и утилизация контейнеров Autofac.
Сематическая разница в том, говорите ли вы, что само по себе задание является одноразовым, или реализация может быть одноразовой .
Из вашего примера ясно, что первое не верно, что задания не являются одноразовыми по своей природе. Поэтому я рекомендую #2, но с методом расширения для централизации try/finally
:
public static void Execute(this IJob job)
{
try
{
job.Run();
}
finally
{
var disposableJob = job as IDisposable;
if(disposableJob != null)
{
disposableJob.Dispose();
}
}
}
Я думаю об этом так. Я бы предпочёл, чтобы разработчик реализовал пустой Dispose
метод, чем забыл реализовать необходимый Dispose
метод.
Я бы выбрал #2 и задокументировал, что любой одноразовый объект будет утилизирован. В основном, если вы становитесь владельцем объекта, вы обязаны распоряжаться объектами, которые реализуют IDisposable.
Если вы читали Effective C#/ More Effective C#, то Билл Вагнер дает тот же самый совет (с которым я, очевидно, согласен ;-)
.