构造函数链中的IDisposable

问题描述 投票:1回答:2

我有以下两个构造函数:

public Source(FileStream fileStream) {
    // Stuff
}

public Source(String fileName) : this(new FileStream(fileName, FileMode.Open)) {
    // Nothing, the other constructor does the work
}

第二个构造函数的问题相当明显,正在创建和使用FileStream,但没有处理。因为它在构造函数链中,所以不可能使用using块。我无法将new FileStream()移动到构造函数的主体中,因为虽然它将在using块中,但是其他构造函数的逻辑将无法被调用。我无法提取出那个逻辑,因为它修改了readonly字段。我可以在每个构造函数中复制逻辑,但这显然不是一个好的解决方案。

我真的更愿意保留第二个构造函数提供的语法糖。我该怎么做才能做到最好?或者这只是一个坏主意?

c# .net idisposable
2个回答
4
投票

看看StreamReader实现,它有两种类型的ctors:

public StreamReader(Stream stream)
      : this(stream, true)
    {
    }

public StreamReader(string path)
      : this(path, true)
    {
    }

在内部,他们都使用参数Init调用相同的leaveOpen方法,该参数设置为第一个ctor的true和第二个ctor的false,并且基于此参数,Stream得到(或不)处理。

所以你可以这样做:

public class Source : IDisposable
{
    private readonly Stream _stream;
    private readonly bool _leaveOpen;

    private Source(Stream stream, bool leaveOpen)
    {
        _stream = stream;
        _leaveOpen = leaveOpen;
    }

    public Source(FileStream fileStream) : this(fileStream, true)
    {

    }

    public Source(string fileName) : this(new FileStream(fileName, FileMode.Open), false)
    {

    }

    public void Dispose()
    {
        if (!_leaveOpen)
        {
            _stream?.Dispose();
        }
    }
}

4
投票

我不确定是什么阻止你在使用FileStream的构造函数中处理它:

public Source(FileStream fileStream) {
    try
    {
        // Stuff
    }
    finally
    {
        fileStream.Dispose();
    }
}

public Source(String fileName) : this(new FileStream(fileName, FileMode.Open)) {
    // Nothing, the other constructor does the work
}

如果是因为你想为Stream构造函数的调用者保持FileStream活着,你可以添加第三个private构造函数:

public Source(FileStream fileStream): this(fileStream, disposeStream: false) {
    // Nothing, the other constructor does the work
}

public Source(String fileName) : this(new FileStream(fileName, FileMode.Open), disposeStream: true) {
    // Nothing, the other constructor does the work
}

private Source(FileStream fileStream, bool disposeStream) {
    try
    {
        // Stuff
    }
    finally
    {
        if (disposeStream)
        {
            fileStream.Dispose();
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.