Reputation: 6174
Often, the IDisposable
object of a using
block is itself constructed from another IDisposable
object, e.g.
using (FileStream stream = File.Open(path, FileMode.Open))
using (MyObject obj = new MyObject(stream))
{
// do something with obj
}
Unfortunately the code above keeps the file stream open until the MyObject
object is disposed.
To dispose of the file stream as soon as the MyObject
constructor has completed, I could instead write:
MyObject CreateMyObject(string path)
{
using (FileStream stream = File.Open(path, FileMode.Open))
{
return new MyObject(stream);
}
}
using (MyObject obj = CreateMyObject(path))
{
// do something with obj
}
But I don't like the verbosity of this solution. I tried replacing CreateMyObject()
with a lambda but I failed to find a legal syntax. Is there a way to do this without calling a custom creator function?
Edit: Bearing in mind some of the comments, I should point out that I'm trying to avoid try
...finally
- kind of the main reason for a using
block in the first place.
Additional clarification: The MyObject object is constructed from information in the stream - i.e. its constructor reads the content of the stream in its entirity. No other method in MyObject references the stream. The content of the stream could come from anywhere - a file, a resource, an Internet socket, etc.
Upvotes: 0
Views: 94
Reputation: 4314
You could invoke some magic like so:
TResult CreateUsingDisposable<TDisposable, TResult>(TDisposable disposable, Func<TDisposable, TResult> getResult)
where TDisposable : IDisposable
{
using (disposable)
{
return getResult(disposable);
}
}
using (var obj = CreateUsingDisposable(new FileStream(path, FileMode.Open), stream => new MyObject(stream)))
{
}
But why? There's a super easy to read no-nonsense way of doing that:
MyObject obj;
using (var stream = new FileStream(path, FileMode.Open))
{
obj = new MyObject(stream);
}
using (obj)
{
}
Upvotes: 1
Reputation: 249686
While I don't see a way to avoid the creator function, you can make it generic enough to define once and use for any class:
static T WithStream<T>(string path, Func<FileStream, T> getter)
{
using (FileStream stream = File.Open(path, FileMode.Open))
{
return getter(stream);
}
}
class MyObject : IDisposable
{
public MyObject (Stream stream){ /* Work with stream */}
public void Dispose(){}
}
static void Main()
{
using (MyObject obj = WithStream("path", fs => new MyObject(fs)))
{
// do something with obj
}
}
Upvotes: 1