XmlWriter - 一次性

XmlWriter - disposable

我无法理解 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 由于未正确处置?

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

如果

中出现异常,可能会导致内存问题
// Do stuff

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

XmlWriter.Dispose calls Close method behind the scene

根据 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 方法。

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

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

在这种情况下,您正在与 StringBuilder 通话。这里的 Dispose() 基本上是空操作,因为那里 没有外部资源 。它会在未来的某个时候以任何一种方式被 GC 收集。因此,不:这里没有内存泄漏问题; GC 可以看到你在做什么。

因此:在这种情况下它不会产生功能上的差异,但是:养成调用 Dispose() 的习惯是很好的做法(通常通过using) 当它是 API 的一部分时,因为在许多情况下这 非常非常重要