【问题标题】:Wrapping stream within a stream - will the wrapped stream be disposed properly?在流中包装流 - 包装的流会被正确处理吗?
【发布时间】:2011-10-17 11:27:54
【问题描述】:

不知道怎么查,例如:

using (var stream = new StreamWriter(someStream))
{
    stream.Write("");
}

这会是这样吗:

using (var stream1 = someStream)
{
    using (var stream2 = new StreamWriter(stream1))
         stream.Write("");
}

或者如果我要包装到 GZipStream 或任何其他流中...第一个示例会处理每个底层流吗?

更新:

最后它击中了我——我自己实现了 Stream 类:

class MyStream : Stream
{
    // fake stream implementation

    protected override void Dispose(bool disposing)
    {
        Console.WriteLine("disposing in my class");
        base.Dispose(disposing);
    }
}

class Program
{
    static void Main(string[] args)
    {
        MyStream stream = new MyStream();
        DoSomething(stream);
        stream.Dispose();

        Console.WriteLine("end of program");
    }

    private static void DoSomething(Stream stream)
    {
        using (var writer = new StreamWriter(stream))
        {
            Console.WriteLine("inside using statement");
        }

        Console.WriteLine("after writing");
    }
}

结果:

inside using statement
disposing in my class
after writing
disposing in my class
end of program

【问题讨论】:

    标签: c# stream dispose word-wrap


    【解决方案1】:

    不,您不能依赖它为任何IDisposable 对象处理底层流(尽管在StreamWriter 的情况下,它被记录为这样做)。一般不要依赖它。

    你应该使用嵌套的 using 语句。

    【讨论】:

    • downvoter....为什么?我说的是正确的,你不应该依赖对象实现 IDisposable 调用 Dispose 对任何成员/参数 IDisposable 对象。
    • 好吧,这就像说你不能依靠包装类来避免崩溃 - 使用我不能依赖于不断表现的框架有什么意义?
    • 在他的示例中使用的类的情况下,这很好,但如果 OP 认为这意味着,对于 IDisposable 对象的所有组合都很好,会有问题。
    • 很多时候,将处理作为参数传入的对象的责任留给调用者是个好主意。在这些情况下,您需要嵌套 usings。
    • 好的,现在这没有任何意义。如果我将我的“someStream”包装在 StreamWriter 中,然后处置 SW,那么“someStream”也将被处置——这就是你们所说的。那么其他人(调用方法)如何再次使用该已处置的对象呢?那行不通……
    【解决方案2】:

    您在这里混合了两个概念。

    主要是使用块嵌套,在第二个示例中,您正确使用了它们。

    第二个问题是嵌套/包装/链接的一次性类。在 StreamWriter 和 Stream 的情况下,Writer 将关闭 Stream。但是您不想知道,只需使用 using 模式即可。

    一个小提示,以下替代布局更易于阅读和维护。添加 GZipStream 时,您将有 3+ 个嵌套 using 块。

    using (var stream1 = File.Create(...))
    using (var stream2 = new StreamWriter(stream1))
    {    
             stream2.Write("");
    }
    

    【讨论】:

    • 总的来说我同意这一点,你应该避免“知识依赖”,但在这种情况下,它也被记录在发生,所以不处置内部流对象是完全安全的。跨度>
    • @Lasse 正确,但无论如何我倾向于避免它。除非是相关的情况,比如在 Writer 之后使用流。
    • 我完全同意你的看法,我也总是处理这样的事情,即使我“知道”在这种特殊情况下这无关紧要,我仍然会这样做。我不希望我或其他开发人员出现在我的代码中并认为“嗯,这很奇怪”只是因为我想“优化”这行代码。
    • 老实说,这就像人们不想在 if's、for's 等下使用单行块。如果这是预期的行为,那么对我来说,如果我包装一些流会更清楚一行 3 次然后缩进 3 次...
    【解决方案3】:

    在最顶部的流上调用 close 会向下级联并将它们全部关闭,但不建议这样做,因为很难密切关注打开的内容和未打开的内容。正如其他回答者所说,虔诚地使用 using 块。

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-28
      • 1970-01-01
      • 1970-01-01
      • 2014-05-24
      • 1970-01-01
      相关资源
      最近更新 更多