Reputation: 108
Let's say I want to use 2 classes which implement the IDispose pattern. One of the classes uses the other for instantiation but is not needed afterwards. When stacking "using" keywords this will result in (for example) a locked file for the duration of using the font. I want the file to be unlocked right after I'm done with it for "coding beauty" reasons.
Have a look at the following "tag-like" system.
using1 (Stream stream = File.OpenRead("font.ttf"))
using2 (Font font = FontExtensions.FromStream(stream, 32))
ENDusing1
//use font here
ENDusing2
The hierarchical way, how code blocks are designed, impose a (beauty) limitation on the current handling of this. Ofcourse this can be solved by using try/finally blocks, but these aren't as neat.
Am I missing a fundamental design with using (lol?) nested IDisposable objects / Streams?
Please share your opinion on tag-code-blocks and the best way to solve this (coding beauty).
Upvotes: 3
Views: 176
Reputation: 144136
You could create a utility method to create your object from a temporary resource:
public static T FromTempResource<T, TDisp>(Func<TDisp> dispFunc, Func<TDisp, T> createFunc) where TDisp : IDisposable
{
using(TDisp d = dispFunc())
{
return createFunc(d);
}
}
your example could then be:
using (Font font = FromTempResource(() => File.OpenRead("font.tt"), stream => FontExtensions.FromStream(stream, 32))
{
}
Upvotes: 2
Reputation: 112402
You can nest the usings and at the same time close or even dispose the stream prematurely.
using (Stream stream = File.OpenRead("font.ttf")) {
using (Font font = FontExtensions.FromStream(stream, 32)) {
stream.Close(); // Or stream.Dispose();
//use font here
}
}
The FileStream
class uses a flag internally to know whether it has been closed or disposed and ensures that this will not happen twice. The Dispose
method just calls the Close
method.
Upvotes: 9