4

我正在使用一个StringWriter我正在传递给一个方法以在foreach循环中写入值的方法。我相信这会导致产生两个警告:

CA2000:Microsoft.Reliability:在方法“ToCsvService.ToCsv()”中,对象“sw”并未沿所有异常路径进行处理。在对对象“sw”的所有引用超出范围之前调用 System.IDisposable.Dispose。

CA2202:Microsoft.Usage:对象“sw”可以在方法“ToCsvService.ToCsv()”中多次处理。为避免生成 System.ObjectDisposedException,您不应在一个对象上多次调用 Dispose。

public string ToCsv()
{
    IEnumerable<string> props = GetProperties();
    StringWriter sw = new StringWriter(); // first warning here
    sw.WriteLine(GetHeadings(props));
    WriteValues(props, sw);

    sw.Close();
    string returnCsv = sw.ToString();
    sw.Dispose(); // second warning here

    return returnCsv;
}

我已经GetProperties()从调用的方法列表中省略了,因为它似乎不相关。

private string GetHeadings(IEnumerable<string> props)
{
    string headings = String.Join(",",
        props.Select(prop =>
            _headings.ContainsKey(prop) ? _headings[prop] : prop));

    return headings;
}

private void WriteValues(IEnumerable<string> props, StringWriter sw)
{
    foreach (object obj in _collection)
    {
        var x = obj.GetType().GetProperties()
            .Where(pi => props.Contains(pi.Name))
            .Select(pi =>
                _format.ContainsKey(pi.Name)
                ? String.Format("{0:" + _format[pi.Name] + "}",
                                pi.GetGetMethod().Invoke(obj, null))
                : pi.GetGetMethod().Invoke(obj, null).ToString());

        string values = String.Join<string>(",", x);

        sw.WriteLine(values);
    }
}

为什么会产生这些警告?

4

2 回答 2

10

您的代码允许抛出异常导致执行跳过关闭您的StringWriter. 您要确保在异常导致执行离开之前ToCSV关闭sw

处理此问题的最简单方法是使用using块。using在退出块的范围之前,保证在子句中构造的对象被释放:

public string ToCsv()
{
    IEnumerable<string> props = GetProperties();
    using (StringWriter sw = new StringWriter())
    {
        sw.WriteLine(GetHeadings(props));
        WriteValues(props, sw);
        return sw.ToString();
    }
}

请注意,您不需要在 StringWriter 上同时调用Close和。Dispose就够Dispose了。

通常,您需要using围绕所有实现的对象的创建和使用包装一个块IDisposable(就像StringWriter这样做一样)。这将确保无论抛出什么异常,该对象总是被正确处理。

于 2010-09-23T23:38:14.333 回答
3

第二个警告是因为 StringWriter.Close() 调用 StringWriter.Dispose(), http: //msdn.microsoft.com/en-us/library/system.io.stringwriter.close.aspx,所以你调用了两次 Dispose。

第一个警告是因为如果在 new StringWriter() 之后出现异常,则没有任何 catch 语句可以对其调用 Dispose。我建议将您的代码重写为

using (StringWriter sw = new StringWriter()) { 
    sw.WriteLine(GetHeadings(props));
    WriteValues(props, sw);
    return sw.ToString();
}
于 2010-09-23T23:40:29.447 回答