I have the following two constructors:
public Source(FileStream fileStream) {
// Stuff
}
public Source(String fileName) : this(new FileStream(fileName, FileMode.Open)) {
// Nothing, the other constructor does the work
}
The issue with the second constructor is rather obvious, a FileStream is being created and used, but not disposed. Because it's inside of a constructor chain, a using
block is not possible. I can't move the new FileStream()
into the body of the constructor because, while it would then be in a using
block, the logic of the other constructor wouldn't be able to be called. I can't extract out that logic because it modifies readonly
fields. I could duplicate the logic in each constructor, but that's obviously not a good solution.
I really would prefer to keep the syntactic sugar the second constructor provides. How can I best do this? Or is this just a bad idea?
Take a look at StreamReader
implementation, which has two types of ctors:
public StreamReader(Stream stream)
: this(stream, true)
{
}
public StreamReader(string path)
: this(path, true)
{
}
Internally they both call the same Init
method with a parameter leaveOpen
, which is set to true
for the first ctor and to false
for the second ctor and based on this parameter the Stream
gets (or not) disposed.
So you can do something like this:
public class Source : IDisposable
{
private readonly Stream _stream;
private readonly bool _leaveOpen;
private Source(Stream stream, bool leaveOpen)
{
_stream = stream;
_leaveOpen = leaveOpen;
}
public Source(FileStream fileStream) : this(fileStream, true)
{
}
public Source(string fileName) : this(new FileStream(fileName, FileMode.Open), false)
{
}
public void Dispose()
{
if (!_leaveOpen)
{
_stream?.Dispose();
}
}
}