当外部仅用于构造内部时避免嵌套使用块
Avoiding nested using blocks when outer is used only to construct inner
通常,using
块的 IDisposable
对象本身是从另一个 IDisposable
对象构建的,例如
using (FileStream stream = File.Open(path, FileMode.Open))
using (MyObject obj = new MyObject(stream))
{
// do something with obj
}
不幸的是,上面的代码使文件流保持打开状态,直到 MyObject
对象被释放。
要在 MyObject
构造函数完成后立即处理文件流,我可以这样写:
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
}
但我不喜欢这个解决方案的冗长。我尝试用 lambda 替换 CreateMyObject()
但我没能找到合法的语法。有没有办法在不调用自定义创建者函数的情况下做到这一点?
编辑:考虑到一些评论,我应该指出我正在努力避免 try
...finally
- 这是 [=13 的主要原因=] 排在第一位。
补充说明:MyObject 对象是根据流中的信息构造的 - 即其构造函数读取整个流的内容。 MyObject 中没有其他方法引用该流。流的内容可以来自任何地方——文件、资源、Internet 套接字等。
虽然我没有看到避免 creator 函数的方法,但您可以使其足够通用以定义一次并用于任何 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
}
}
你可以像这样调用一些魔法:
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)))
{
}
但是为什么呢?有一种非常容易阅读的严肃方法:
MyObject obj;
using (var stream = new FileStream(path, FileMode.Open))
{
obj = new MyObject(stream);
}
using (obj)
{
}
通常,using
块的 IDisposable
对象本身是从另一个 IDisposable
对象构建的,例如
using (FileStream stream = File.Open(path, FileMode.Open))
using (MyObject obj = new MyObject(stream))
{
// do something with obj
}
不幸的是,上面的代码使文件流保持打开状态,直到 MyObject
对象被释放。
要在 MyObject
构造函数完成后立即处理文件流,我可以这样写:
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
}
但我不喜欢这个解决方案的冗长。我尝试用 lambda 替换 CreateMyObject()
但我没能找到合法的语法。有没有办法在不调用自定义创建者函数的情况下做到这一点?
编辑:考虑到一些评论,我应该指出我正在努力避免 try
...finally
- 这是 [=13 的主要原因=] 排在第一位。
补充说明:MyObject 对象是根据流中的信息构造的 - 即其构造函数读取整个流的内容。 MyObject 中没有其他方法引用该流。流的内容可以来自任何地方——文件、资源、Internet 套接字等。
虽然我没有看到避免 creator 函数的方法,但您可以使其足够通用以定义一次并用于任何 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
}
}
你可以像这样调用一些魔法:
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)))
{
}
但是为什么呢?有一种非常容易阅读的严肃方法:
MyObject obj;
using (var stream = new FileStream(path, FileMode.Open))
{
obj = new MyObject(stream);
}
using (obj)
{
}