当外部仅用于构造内部

时间:2018-07-05 14:04:29

标签: c# using idisposable

通常,IDisposable块的using对象本身是由另一个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-这是产生using的主要原因首先阻止。

其他说明:MyObject对象是根据流中的信息构造的,即,其构造函数以其整体来读取流的内容。 MyObject中没有其他方法引用该流。流的内容可能来自任何地方-文件,资源,Internet套接字等。

2 个答案:

答案 0 :(得分:2)

您可以像这样调用一些魔术:

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

  }

答案 1 :(得分:1)

虽然我看不到一种避免使用creator函数的方法,但您可以使其通用到足以定义一次并用于任何类:

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
    }
}