【问题标题】:XmlWriter - disposableXmlWriter - 一次性
【发布时间】:2020-02-14 10:16:17
【问题描述】:

我无法理解 XmlWriter 在 C# 中的工作方式。把下面的代码当作假设在某个地方使用过。

StringBuilder builder = new StringBuilder();
XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = new UTF8Encoding(false);
settings.ConformanceLevel = ConformanceLevel.Document;
settings.Indent = true;

XmlWriter writer = XmlWriter.Create(builder, settings);

// Do stuff

writer.Close();

由于 XmlWriter 未在 using 语句中使用,这是否可能由于未正确处理而导致 OutOfMemoryException

【问题讨论】:

  • Close,在这种情况下与 Dispose 几乎相同,但使用“using”是语法糖,确保您不会错过 close。另外,我应该补充一点,不仅需要关闭一些引用,而且需要发送信号流,一切都已完成并且所有数据都应该完全发送。只有这样你才能使用构建器值。

标签: c# xmlwriter


【解决方案1】:

最终,在这种情况下,Dispose() 的目的是允许 XmlWriter 承担它正在写入的任何内容的所有权 - 例如,如果您创建一个 XmlWriter over一个Stream,在XmlWriter 上调用Dispose() 可以(默认情况下)刷新xml 编写器然后在流上调用Dispose()。这使得将 XmlWriter 传递给 API 变得容易,而不必向它们传递完成后需要处理的其他对象链(例如,它可以是 XmlWriterCompressionStream 交谈与SslStream 交谈,与NetworkStream 交谈等)。

一般情况中,最终结果上的Dispose() 的目的是关闭底层资源(可能是文件、套接字、管道等)

在这种特定情况下,您正在与StringBuilder 交谈。这里的Dispose() 基本上是无操作的,因为没有外部资源。无论哪种方式,它都会在将来的某个时候被 GC 收集。因此,不:这里没有内存泄漏问题; GC 可以看到你在做什么。

所以:在这种情况下它不会产生功能上的差异,但是:养成拨打Dispose()(通常通过using)的习惯是一个好习惯API 的一部分,因为在许多情况下,这非常非常重要

【讨论】:

    【解决方案2】:

    拥有using 块很好,它确保在任何实现IDisposable 的对象上调用Dispose

    using (XmlWriter writer = XmlWriter.Create(builder, settings))
    {
         //do stuff
    }
    

    XmlWriterDispose 方法看起来像-

    protected virtual void Dispose(bool disposing)
    {
        if (this.WriteState != WriteState.Closed)
        {
            try
            {
                this.Close();
            }
            catch
            {
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      如果出现异常,可能会导致内存问题

      // Do stuff
      

      在这种情况下,不会执行 Close 方法。 using 语句是 try-finally 块周围的语法糖。即使出现异常,它也会在 finally 块中调用 Dispose

      XmlWriter.Dispose calls Close method behind the scene

      【讨论】:

        【解决方案4】:

        根据 c# 文档 using 语句确保即使在 using 块中发生异常,也会调用 Dispose。您可以通过将对象放在 try 块中,然后在 finally 块中调用 Dispose 来获得相同的结果;事实上,这就是编译器翻译 using 语句的方式。前面的代码示例在编译时扩展为以下代码(注意额外的花括号以创建对象的有限范围):

                {
                    var font1 = new Font("Arial", 10.0f);
                    try
                    {
                        byte charset = font1.GdiCharSet;
                    }
                    finally
                    {
                        if (font1 != null)
                            ((IDisposable)font1).Dispose();
                    }
                }
        

        和关闭功能是做同样的事情 此方法调用 Dispose,指定 true 以释放所有资源。您不必专门调用 Close 方法。相反,请确保正确处置每个 Stream 对象。您可以在 using 块(或 Visual Basic 中的 Using 块)中声明 Stream 对象,以确保释放流及其所有资源,也可以显式调用 Dispose 方法。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-10-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多