У меня есть небольшая иерархия объектов, которая обычно создается из данных в Stream
, но для некоторых конкретных подклассов может быть синтезирована из более простого списка аргументов. При объединении конструкторов из подклассов я сталкиваюсь с проблемой обеспечения удаления синтезированного потока, который необходим конструктору базового класса. Не ускользнуло от меня тот факт, что использование IDisposable
объектов таким способом, возможно, является просто грязным пулом (пожалуйста, посоветуете?) По причинам, которые я не рассмотрел, но, если оставить в стороне эту проблему, она кажется довольно простой (и с хорошей инкапсуляцией).
Коды:
abstract class Node {
protected Node (Stream raw)
{
// calculate/generate some base class properties
}
}
class FilesystemNode : Node {
public FilesystemNode (FileStream fs)
: base (fs)
{
// all good here; disposing of fs not our responsibility
}
}
class CompositeNode : Node {
public CompositeNode (IEnumerable some_stuff)
: base (GenerateRaw (some_stuff))
{
// rogue stream from GenerateRaw now loose in the wild!
}
static Stream GenerateRaw (IEnumerable some_stuff)
{
var content = new MemoryStream ();
// molest elements of some_stuff into proper format, write to stream
content.Seek (0, SeekOrigin.Begin);
return content;
}
}
Я понимаю, что не выбрасывание MemoryStream
- это не совсем бесполезный случай плохого гражданства CLR, но это все же дает мне хиби-джеби (не говоря уже о том, что я не всегда могу использовать MemoryStream
для других подтипов). Это не входит в область видимости, поэтому я не могу явно Dispose ()
это позже в конструкторе, и добавление оператора using
в GenerateRaw ()
самоубийственно, так как мне нужен возвращаемый поток.
Есть ли лучший способ сделать это?
Упреждающие удары:
- да, свойства, рассчитанные в конструкторе
Node
, должны быть частью базового класса и не должны рассчитываться (или доступны в) подклассами
- Я не буду требовать, чтобы поток передавался в CompositeNode (его формат не должен относиться к вызывающей стороне)
- На предыдущей итерации вычисление значения в базовом классе выполнялось как отдельный защищенный метод, который я затем просто вызывал в конце каждого конструктора подтипа, перемещая тело
GenerateRaw ()
в оператор using в теле CompositeNode
конструктор. Но повторение требования этого вызова для каждого конструктора и неспособность гарантировать, что он будет выполняться для каждого подтипа когда-либо (Node
не является Node
, семантически, без инициализации этих свойств), сделало меня гораздо хуже чем (потенциальная) утечка ресурсов здесь.