当外部仅用于构造内部时避免嵌套使用块

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)
  {

  }