首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在没有代码分析警告的情况下同时使用StringWriter和HtmlWriter

如何在没有代码分析警告的情况下同时使用StringWriter和HtmlWriter
EN

Stack Overflow用户
提问于 2012-01-11 06:21:44
回答 3查看 4.1K关注 0票数 5

我使用的是.net,需要获取一些html文本,所以我想我应该结合使用HtmlTextWriter和StringWriter来获得格式良好的html。但是,尽管我以各种不同的方式编写代码,我仍然会收到来自静态代码分析器的警告(使用Microsoft all Rules)。在下面的代码示例中,我在注释中显示了代码分析器警告。为了简化代码,我实际上没有对HtmlTextWriter进行任何调用(您将在每个函数中看到相应的注释)。如何正确编写代码以避免出现警告?

代码语言:javascript
复制
// CA2000 : Microsoft.Reliability : In method 'Default.Func1()', object 'stringWriter' is not disposed along all exception paths. Call System.IDisposable.Dispose on object 'stringWriter' before all references to it are out of scope.
public static string Func1()
{
    string html;
    StringWriter stringWriter;
    using (var writer = new HtmlTextWriter(stringWriter = new StringWriter()))
    {
        // You would do some stuff with the writer here, but not for this example.

        html = stringWriter.ToString();
    }
    return html;
}

// CA2202 : Microsoft.Usage : Object 'stringWriter' can be disposed more than once in method 'Default.Func2()'. To avoid generating a System.ObjectDisposedException you should not call Dispose more than one time on an object.: Lines: 45
public static string Func2()
{
    string html;
    StringWriter stringWriter = null;
    try
    {
        using (var writer = new HtmlTextWriter(stringWriter = new StringWriter()))
        {
            // You would do some stuff with the writer here, but not for this example.

            html = stringWriter.ToString();
        }
    }
    finally
    {
        if (stringWriter != null)
            stringWriter.Dispose();
    }
    return html;
}

// CA2202 : Microsoft.Usage : Object 'stringWriter' can be disposed more than once in
// method 'Default.Func3()'. To avoid generating a System.ObjectDisposedException 
// you should not call Dispose more than one time on an object.: Lines: 61
public static string Func3()
{
    string html;
    using (var stringWriter = new StringWriter())
    {
        using (var writer = new HtmlTextWriter(stringWriter))
        {
            // You would do some stuff with the writer here, but not for this example.

            html = stringWriter.ToString();
        }
    }
    return html;
}

// CA2202 : Microsoft.Usage : Object 'stringWriter' can be disposed more than once in 
// method 'Default.Func4()'. To avoid generating a System.ObjectDisposedException you 
// should not call Dispose more than one time on an object.: Lines: 77
public static string Func4()
{
    string html;
    using (StringWriter stringWriter = new StringWriter())
    {
        using (HtmlTextWriter writer = new HtmlTextWriter(stringWriter))
        {
            // You would do some stuff with the writer here, but not for this example.

            html = stringWriter.ToString();
        }
    }
    return html;
}

// CA2202 : Microsoft.Usage : Object 'stringWriter' can be disposed more than once in 
// method 'Default.Func5()'. To avoid generating a System.ObjectDisposedException you 
// should not call Dispose more than one time on an object.: Lines: 100
public static string Func5()
{
    string html;
    StringWriter stringWriter = null;
    try
    {
        stringWriter = new StringWriter();
        using (HtmlTextWriter htmlTextWriter = new HtmlTextWriter(stringWriter))
        {
            // You would do some stuff with the writer here, but not for this example.

            html = stringWriter.ToString();
        }
    }
    finally
    {
        if (stringWriter != null)
            stringWriter.Dispose();
    }
    return html;
}
EN

回答 3

Stack Overflow用户

发布于 2013-09-18 02:50:08

修改您的Func5如下:

代码语言:javascript
复制
public static string Func5()
{
    string html;
    StringWriter stringWriter = null;
    try
    {
        stringWriter = new StringWriter();
        using (HtmlTextWriter htmlTextWriter = new HtmlTextWriter(stringWriter))
        {
            stringWriter = null;

            // You would do some stuff with the writer here, but not for this example.

            html = htmlTextWriter.InnerWriter.ToString();
        }
    }
    finally
    {
        if (stringWriter != null)
            stringWriter.Dispose();
    }
    return html;
}

关键是将stringWriter变量设置为null (这不会影响HtmlTextWriter实例的InnerWriter ),然后使用InnerWriter.ToString()获取HtmlTextWriter。

这实际上只是MSDN文章中示例的修改版本,在前面的评论中引用,但仅适用于您的用法。

票数 1
EN

Stack Overflow用户

发布于 2014-12-06 07:04:04

实际上,没有办法使此代码避免警告,因为在这种特殊情况下,代码分析是错误的。

正确的代码是添加CodeAnalysis.SuppressMessage属性的Func3:

代码语言:javascript
复制
// Code Analysis is incorrectly assuming that HtmlTextWriter.Dispose will dispose of the InnerWriter, but it actually does not.
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
public static string Func3()
{
    string html;
    using (var stringWriter = new StringWriter())
    {
        using (var writer = new HtmlTextWriter(stringWriter))
        {
            // You would do some stuff with the writer here, but not for this example.

            // I prefer to use writer.InnerWriter as opposed to stringWriter for clarity.
            html = writer.InnerWriter.ToString();
        }
    }
    return html;
}

CA2202的文档使用了一个StreamWriter处理其流的示例,这是正确的,但是HtmlTextWriter没有处理它的内部TextWriter (可以通过对StringWriter进行子类化并在override dispose中设置断点来验证)。这有点让人困惑,因为HtmlTextWriter派生自TextWriter,而StringWriter也派生自TextWriter (而不是StreamWriter,它的Stream是两个完全不同的类),那么为什么HtmlTextWriter需要InnerWriter呢?…但不管怎样,这就是它的工作方式。

此外,文档还说不要取消显示此警告,因为“即使已知对象的Dispose可以多次安全地调用,实现将来也可能会发生变化。”但是,在这种情况下,Dispose是而不是被多次调用,因此可以安全地取消该警告。

但是不要相信我的话!这就是证据:

代码语言:javascript
复制
using System;
using System.IO;
using System.Web.UI;

namespace WebApplication1
{
    public partial class WebForm1 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            StreamWillBeDisposed();
            TextWriterWillNotBeDisposed();
        }

        public static void StreamWillBeDisposed()
        {
            Stream stream = new DebugMemoryStream();
            using (StreamWriter writer = new StreamWriter(stream))
            {
                // Use the writer object...
            }// Underlying Stream will be disposed here by the StreamWriter
        }

        public static void TextWriterWillNotBeDisposed()
        {
            TextWriter stringWriter = new DebugStringWriter();
            using (HtmlTextWriter writer = new HtmlTextWriter(stringWriter))
            {
                // Use the writer object...
            }// Underlying TextWriter will NOT be disposed here by the HtmlTextWriter
        }
    }


    public class DebugMemoryStream : MemoryStream
    {
        protected override void Dispose(bool disposing)
        {
            // This Stream will be disposed when the StreamWriter is disposed
            System.Diagnostics.Debugger.Break();
            base.Dispose(disposing);
        }
    }

    public class DebugStringWriter : StringWriter
    {
        protected override void Dispose(bool disposing)
        {
            // This code will never see the light of day
            System.Diagnostics.Debugger.Break();
            base.Dispose(disposing);
        }
    }

}
票数 1
EN

Stack Overflow用户

发布于 2012-01-11 06:36:33

因为StringWriter是可丢弃的,所以你可以用另一个来包装你的内部写入器。

代码语言:javascript
复制
using (StringWriter stringWriter = new StringWriter())
{
    using (var writer = new HtmlTextWriter(stringWriter))
    {
         html = stringWriter.ToString();  
    }
}
return html;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8811383

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档